[wpilib] Allow SendableCameraWrappers to take arbitrary URLs (#3850)

Useful for adding cameras that are streamed from a coprocessor

Co-authored-by: Peter Johnson <johnson.peter@gmail.com>
Co-authored-by: Sam Carlberg <sam.carlberg@gmail.com>
This commit is contained in:
Peter Johnson
2022-01-01 10:10:37 -08:00
committed by GitHub
parent a3645dea34
commit ecee224e81
6 changed files with 191 additions and 19 deletions

View File

@@ -7,9 +7,13 @@
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#ifndef DYNAMIC_CAMERA_SERVER
#include <cscore_oo.h>
#include <fmt/format.h>
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableInstance.h>
#else
namespace cs {
class VideoSource;
@@ -20,6 +24,7 @@ using CS_Source = CS_Handle; // NOLINT
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
#include <wpi/span.h>
namespace frc {
@@ -28,8 +33,8 @@ class SendableCameraWrapper;
namespace detail {
constexpr const char* kProtocol = "camera_server://";
std::shared_ptr<SendableCameraWrapper>& GetSendableCameraWrapper(
CS_Source source);
void AddToSendableRegistry(wpi::Sendable* sendable, std::string name);
std::string_view cameraName);
void AddToSendableRegistry(wpi::Sendable* sendable, std::string_view name);
} // namespace detail
/**
@@ -46,9 +51,9 @@ class SendableCameraWrapper
* Creates a new sendable wrapper. Private constructor to avoid direct
* instantiation with multiple wrappers floating around for the same camera.
*
* @param source the source to wrap
* @param cameraName the name of the camera to wrap
*/
SendableCameraWrapper(CS_Source source, const private_init&);
SendableCameraWrapper(std::string_view cameraName, const private_init&);
/**
* Gets a sendable wrapper object for the given video source, creating the
@@ -61,6 +66,9 @@ class SendableCameraWrapper
static SendableCameraWrapper& Wrap(const cs::VideoSource& source);
static SendableCameraWrapper& Wrap(CS_Source source);
static SendableCameraWrapper& Wrap(std::string_view cameraName,
wpi::span<const std::string> cameraUrls);
void InitSendable(wpi::SendableBuilder& builder) override;
private:
@@ -68,11 +76,9 @@ class SendableCameraWrapper
};
#ifndef DYNAMIC_CAMERA_SERVER
inline SendableCameraWrapper::SendableCameraWrapper(CS_Source source,
inline SendableCameraWrapper::SendableCameraWrapper(std::string_view name,
const private_init&)
: m_uri(detail::kProtocol) {
CS_Status status = 0;
auto name = cs::GetSourceName(source, &status);
detail::AddToSendableRegistry(this, name);
m_uri += name;
}
@@ -83,12 +89,27 @@ inline SendableCameraWrapper& SendableCameraWrapper::Wrap(
}
inline SendableCameraWrapper& SendableCameraWrapper::Wrap(CS_Source source) {
auto& wrapper = detail::GetSendableCameraWrapper(source);
CS_Status status = 0;
auto name = cs::GetSourceName(source, &status);
auto& wrapper = detail::GetSendableCameraWrapper(name);
if (!wrapper) {
wrapper = std::make_shared<SendableCameraWrapper>(source, private_init{});
wrapper = std::make_shared<SendableCameraWrapper>(name, private_init{});
}
return *wrapper;
}
inline SendableCameraWrapper& SendableCameraWrapper::Wrap(
std::string_view cameraName, wpi::span<const std::string> cameraUrls) {
auto& wrapper = detail::GetSendableCameraWrapper(cameraName);
if (!wrapper) {
wrapper =
std::make_shared<SendableCameraWrapper>(cameraName, private_init{});
}
auto streams = fmt::format("/CameraPublisher/{}/streams", cameraName);
nt::NetworkTableInstance::GetDefault().GetEntry(streams).SetStringArray(
cameraUrls);
return *wrapper;
}
#endif
} // namespace frc

View File

@@ -127,6 +127,18 @@ class ShuffleboardContainer : public virtual ShuffleboardValue {
*/
ComplexWidget& Add(std::string_view title, const cs::VideoSource& video);
/**
* Adds a widget to this container to display a video stream.
*
* @param title the title of the widget
* @param cameraName the name of the streamed camera
* @param cameraUrls the URLs with which the dashboard can access the camera
* stream
* @return a widget to display the camera stream
*/
ComplexWidget& AddCamera(std::string_view title, std::string_view cameraName,
wpi::span<const std::string> cameraUrls);
/**
* Adds a widget to this container to display the given sendable.
*
@@ -526,4 +538,10 @@ inline frc::ComplexWidget& frc::ShuffleboardContainer::Add(
std::string_view title, const cs::VideoSource& video) {
return Add(title, frc::SendableCameraWrapper::Wrap(video));
}
inline frc::ComplexWidget& frc::ShuffleboardContainer::AddCamera(
std::string_view title, std::string_view cameraName,
wpi::span<const std::string> cameraUrls) {
return Add(title, frc::SendableCameraWrapper::Wrap(cameraName, cameraUrls));
}
#endif