From 06108b9479b5cad616cc5686df835e30503399eb Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sun, 4 Dec 2016 00:26:08 -0800 Subject: [PATCH] Update CameraServer support. (#386) * Follow MixedCase rename. * Add GetVideo function to get cameras by name. --- wpilibc/athena/include/CameraServer.h | 28 ++++++--- wpilibc/athena/src/CameraServer.cpp | 51 ++++++++++----- .../edu/wpi/first/wpilibj/CameraServer.java | 63 ++++++++++++------- 3 files changed, 96 insertions(+), 46 deletions(-) diff --git a/wpilibc/athena/include/CameraServer.h b/wpilibc/athena/include/CameraServer.h index d413ad232c..d5dcb2f88c 100644 --- a/wpilibc/athena/include/CameraServer.h +++ b/wpilibc/athena/include/CameraServer.h @@ -44,16 +44,20 @@ class CameraServer : public ErrorBase { * If you also want to perform vision processing on the roboRIO, use * getVideo() to get access to the camera images. * - * This overload calls {@link #startAutomaticCapture(int)} with device 0. + * This overload calls {@link #StartAutomaticCapture(int)} with device 0, + * creating a camera named "USB Camera 0". */ - cs::USBCamera StartAutomaticCapture(); + cs::UsbCamera StartAutomaticCapture(); /** * Start automatically capturing images to send to the dashboard. * + *

This overload calls {@link #StartAutomaticCapture(String, int)} with + * a name of "USB Camera {dev}". + * * @param dev The device number of the camera interface */ - cs::USBCamera StartAutomaticCapture(int dev); + cs::UsbCamera StartAutomaticCapture(int dev); /** * Start automatically capturing images to send to the dashboard. @@ -61,7 +65,7 @@ class CameraServer : public ErrorBase { * @param name The name to give the camera * @param dev The device number of the camera interface */ - cs::USBCamera StartAutomaticCapture(llvm::StringRef name, int dev); + cs::UsbCamera StartAutomaticCapture(llvm::StringRef name, int dev); /** * Start automatically capturing images to send to the dashboard. @@ -69,7 +73,7 @@ class CameraServer : public ErrorBase { * @param name The name to give the camera * @param path The device path (e.g. "/dev/video0") of the camera */ - cs::USBCamera StartAutomaticCapture(llvm::StringRef name, + cs::UsbCamera StartAutomaticCapture(llvm::StringRef name, llvm::StringRef path); /** @@ -97,6 +101,14 @@ class CameraServer : public ErrorBase { */ cs::CvSink GetVideo(const cs::VideoSource& camera); + /** + * 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 + */ + cs::CvSink GetVideo(llvm::StringRef name); + /** * Create a MJPEG stream with OpenCV input. This can be called to pass custom * annotated images to the dashboard. @@ -112,14 +124,14 @@ class CameraServer : public ErrorBase { * * @param name Server name */ - cs::MJPEGServer AddServer(llvm::StringRef name); + cs::MjpegServer AddServer(llvm::StringRef name); /** * Adds a MJPEG server. * * @param name Server name */ - cs::MJPEGServer AddServer(llvm::StringRef name, int port); + cs::MjpegServer AddServer(llvm::StringRef name, int port); /** * Adds an already created server. @@ -154,7 +166,7 @@ class CameraServer : public ErrorBase { * the correct mode, or set it directly on a camera and call the appropriate * StartAutomaticCapture method. * - * @deprecated Use SetResolution on the USBCamera returned by + * @deprecated Use SetResolution on the UsbCamera returned by * StartAutomaticCapture() instead. * @param size The size to use */ diff --git a/wpilibc/athena/src/CameraServer.cpp b/wpilibc/athena/src/CameraServer.cpp index 352a730aa8..5ffae00a3f 100644 --- a/wpilibc/athena/src/CameraServer.cpp +++ b/wpilibc/athena/src/CameraServer.cpp @@ -24,14 +24,14 @@ static llvm::StringRef MakeSourceValue(CS_Source source, CS_Status status = 0; buf.clear(); switch (cs::GetSourceKind(source, &status)) { - case cs::VideoSource::kUSB: { + case cs::VideoSource::kUsb: { llvm::StringRef prefix{"usb:"}; buf.append(prefix.begin(), prefix.end()); - auto path = cs::GetUSBCameraPath(source, &status); + auto path = cs::GetUsbCameraPath(source, &status); buf.append(path.begin(), path.end()); break; } - case cs::VideoSource::kHTTP: { + case cs::VideoSource::kHttp: { llvm::StringRef prefix{"ip:"}; buf.append(prefix.begin(), prefix.end()); // TODO @@ -64,8 +64,8 @@ void CameraServer::UpdateStreamValues() { // Over all the sinks... for (const auto& i : m_sinks) { CS_Status status = 0; - // Ignore all but MJPEGServer - if (i.second.GetKind() != cs::VideoSink::kMJPEG) continue; + // Ignore all but MjpegServer + if (i.second.GetKind() != cs::VideoSink::kMjpeg) continue; CS_Sink sink = i.second.GetHandle(); // Get the source's subtable (if none exists, we're done) @@ -74,11 +74,11 @@ void CameraServer::UpdateStreamValues() { if (!table) continue; // Get port - int port = cs::GetMJPEGServerPort(sink, &status); + int port = cs::GetMjpegServerPort(sink, &status); // Generate values std::vector values; - auto listenAddress = cs::GetMJPEGServerListenAddress(sink, &status); + auto listenAddress = cs::GetMjpegServerListenAddress(sink, &status); if (!listenAddress.empty()) { // If a listen address is specified, only use that values.emplace_back(MakeStreamValue(listenAddress, port)); @@ -197,30 +197,30 @@ CameraServer::CameraServer() 0x7fff, true}; } -cs::USBCamera CameraServer::StartAutomaticCapture() { +cs::UsbCamera CameraServer::StartAutomaticCapture() { return StartAutomaticCapture(0); } -cs::USBCamera CameraServer::StartAutomaticCapture(int dev) { +cs::UsbCamera CameraServer::StartAutomaticCapture(int dev) { llvm::SmallString<64> buf; llvm::raw_svector_ostream name{buf}; name << "USB Camera " << dev; - cs::USBCamera camera{name.str(), dev}; + cs::UsbCamera camera{name.str(), dev}; StartAutomaticCapture(camera); return camera; } -cs::USBCamera CameraServer::StartAutomaticCapture(llvm::StringRef name, +cs::UsbCamera CameraServer::StartAutomaticCapture(llvm::StringRef name, int dev) { - cs::USBCamera camera{name, dev}; + cs::UsbCamera camera{name, dev}; StartAutomaticCapture(camera); return camera; } -cs::USBCamera CameraServer::StartAutomaticCapture(llvm::StringRef name, +cs::UsbCamera CameraServer::StartAutomaticCapture(llvm::StringRef name, llvm::StringRef path) { - cs::USBCamera camera{name, path}; + cs::UsbCamera camera{name, path}; StartAutomaticCapture(camera); return camera; } @@ -278,6 +278,23 @@ cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera) { return newsink; } +cs::CvSink CameraServer::GetVideo(llvm::StringRef name) { + cs::VideoSource source; + { + std::lock_guard lock(m_mutex); + auto it = m_sources.find(name); + if (it == m_sources.end()) { + llvm::SmallString<64> buf; + llvm::raw_svector_ostream err{buf}; + err << "could not find camera " << name; + wpi_setWPIErrorWithContext(CameraServerError, err.str()); + return cs::CvSink{}; + } + source = it->second; + } + return GetVideo(source); +} + cs::CvSource CameraServer::PutVideo(llvm::StringRef name, int width, int height) { cs::CvSource source{name, cs::VideoMode::kMJPEG, width, height, 30}; @@ -285,7 +302,7 @@ cs::CvSource CameraServer::PutVideo(llvm::StringRef name, int width, return source; } -cs::MJPEGServer CameraServer::AddServer(llvm::StringRef name) { +cs::MjpegServer CameraServer::AddServer(llvm::StringRef name) { int port; { std::lock_guard lock(m_mutex); @@ -294,8 +311,8 @@ cs::MJPEGServer CameraServer::AddServer(llvm::StringRef name) { return AddServer(name, port); } -cs::MJPEGServer CameraServer::AddServer(llvm::StringRef name, int port) { - cs::MJPEGServer server{name, port}; +cs::MjpegServer CameraServer::AddServer(llvm::StringRef name, int port) { + cs::MjpegServer server{name, port}; AddServer(server); return server; } diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/CameraServer.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/CameraServer.java index d74840bfc5..7f981c260b 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/CameraServer.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/CameraServer.java @@ -10,8 +10,8 @@ package edu.wpi.first.wpilibj; import edu.wpi.cscore.CameraServerJNI; import edu.wpi.cscore.CvSink; import edu.wpi.cscore.CvSource; -import edu.wpi.cscore.MJPEGServer; -import edu.wpi.cscore.USBCamera; +import edu.wpi.cscore.MjpegServer; +import edu.wpi.cscore.UsbCamera; import edu.wpi.cscore.VideoEvent; import edu.wpi.cscore.VideoException; import edu.wpi.cscore.VideoListener; @@ -64,9 +64,9 @@ public class CameraServer { @SuppressWarnings("JavadocMethod") private static String makeSourceValue(int source) { switch (VideoSource.getKindFromInt(CameraServerJNI.getSourceKind(source))) { - case kUSB: - return "usb:" + CameraServerJNI.getUSBCameraPath(source); - case kHTTP: + case kUsb: + return "usb:" + CameraServerJNI.getUsbCameraPath(source); + case kHttp: // TODO return "ip:"; case kCv: @@ -90,8 +90,8 @@ public class CameraServer { private synchronized void updateStreamValues() { // Over all the sinks... for (VideoSink i : m_sinks.values()) { - // Ignore all but MJPEGServer - if (i.getKind() != VideoSink.Kind.kMJPEG) { + // Ignore all but MjpegServer + if (i.getKind() != VideoSink.Kind.kMjpeg) { continue; } int sink = i.getHandle(); @@ -104,11 +104,11 @@ public class CameraServer { } // Get port - int port = CameraServerJNI.getMJPEGServerPort(sink); + int port = CameraServerJNI.getMjpegServerPort(sink); // Generate values ArrayList values = new ArrayList(m_addresses.length + 1); - String listenAddress = CameraServerJNI.getMJPEGServerListenAddress(sink); + String listenAddress = CameraServerJNI.getMjpegServerListenAddress(sink); if (!listenAddress.isEmpty()) { // If a listen address is specified, only use that values.add(makeStreamValue(listenAddress, port)); @@ -242,19 +242,23 @@ public class CameraServer { * If you also want to perform vision processing on the roboRIO, use * getVideo() to get access to the camera images. * - *

This overload calls {@link #startAutomaticCapture(int)} with device 0. + *

This overload calls {@link #startAutomaticCapture(int)} with device 0, + * creating a camera named "USB Camera 0". */ - public USBCamera startAutomaticCapture() { + public UsbCamera startAutomaticCapture() { return startAutomaticCapture(0); } /** * Start automatically capturing images to send to the dashboard. * + *

This overload calls {@link #startAutomaticCapture(String, int)} with + * a name of "USB Camera {dev}". + * * @param dev The device number of the camera interface */ - public USBCamera startAutomaticCapture(int dev) { - USBCamera camera = new USBCamera("USB Camera " + dev, dev); + public UsbCamera startAutomaticCapture(int dev) { + UsbCamera camera = new UsbCamera("USB Camera " + dev, dev); startAutomaticCapture(camera); return camera; } @@ -265,8 +269,8 @@ public class CameraServer { * @param name The name to give the camera * @param dev The device number of the camera interface */ - public USBCamera startAutomaticCapture(String name, int dev) { - USBCamera camera = new USBCamera(name, dev); + public UsbCamera startAutomaticCapture(String name, int dev) { + UsbCamera camera = new UsbCamera(name, dev); startAutomaticCapture(camera); return camera; } @@ -277,8 +281,8 @@ public class CameraServer { * @param name The name to give the camera * @param path The device path (e.g. "/dev/video0") of the camera */ - public USBCamera startAutomaticCapture(String name, String path) { - USBCamera camera = new USBCamera(name, path); + public UsbCamera startAutomaticCapture(String name, String path) { + UsbCamera camera = new UsbCamera(name, path); startAutomaticCapture(camera); return camera; } @@ -342,6 +346,23 @@ public class CameraServer { return newsink; } + /** + * 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 + */ + public CvSink getVideo(String name) { + VideoSource source; + synchronized (this) { + source = m_sources.get(name); + if (source == null) { + throw new VideoException("could not find camera " + name); + } + } + return getVideo(source); + } + /** * Create a MJPEG stream with OpenCV input. This can be called to pass custom * annotated images to the dashboard. @@ -361,7 +382,7 @@ public class CameraServer { * * @param name Server name */ - public MJPEGServer addServer(String name) { + public MjpegServer addServer(String name) { int port; synchronized (this) { port = m_nextPort; @@ -375,8 +396,8 @@ public class CameraServer { * * @param name Server name */ - public MJPEGServer addServer(String name, int port) { - MJPEGServer server = new MJPEGServer(name, port); + public MjpegServer addServer(String name, int port) { + MjpegServer server = new MjpegServer(name, port); addServer(server); return server; } @@ -433,7 +454,7 @@ public class CameraServer { * Sets the size of the image to use. Use the public kSize constants to set the correct mode, or * set it directly on a camera and call the appropriate startAutomaticCapture method. * - * @deprecated Use setResolution on the USBCamera returned by startAutomaticCapture() instead. + * @deprecated Use setResolution on the UsbCamera returned by startAutomaticCapture() instead. * @param size The size to use */ @Deprecated