Merge .inc files into headers (#7215)

This commit is contained in:
Tyler Veness
2024-10-15 23:42:57 -07:00
committed by GitHub
parent 40caabea23
commit fad06ae1e7
25 changed files with 913 additions and 1520 deletions

View File

@@ -9,10 +9,10 @@
#include <span>
#include <string>
#include <string_view>
#include <vector>
#include <wpi/deprecated.h>
#include "cscore.h"
#include "cscore_cv.h"
namespace frc {
@@ -130,7 +130,9 @@ class CameraServer {
*/
template <typename T>
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
static cs::AxisCamera AddAxisCamera(std::initializer_list<T> hosts);
static cs::AxisCamera AddAxisCamera(std::initializer_list<T> hosts) {
return AddAxisCamera("Axis Camera", hosts);
}
/**
* Adds an Axis IP camera.
@@ -185,7 +187,14 @@ class CameraServer {
template <typename T>
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
static cs::AxisCamera AddAxisCamera(std::string_view name,
std::initializer_list<T> hosts);
std::initializer_list<T> hosts) {
std::vector<std::string> vec;
vec.reserve(hosts.size());
for (const auto& host : hosts) {
vec.emplace_back(host);
}
return AddAxisCamera(name, vec);
}
WPI_UNIGNORE_DEPRECATED
/**
@@ -316,5 +325,3 @@ class CameraServer {
};
} // namespace frc
#include "cameraserver/CameraServer.inc"

View File

@@ -1,33 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <string>
#include <vector>
#include "cameraserver/CameraServer.h"
namespace frc {
WPI_IGNORE_DEPRECATED
template <typename T>
inline cs::AxisCamera CameraServer::AddAxisCamera(
std::initializer_list<T> hosts) {
return AddAxisCamera("Axis Camera", hosts);
}
template <typename T>
inline cs::AxisCamera CameraServer::AddAxisCamera(
std::string_view name, std::initializer_list<T> hosts) {
std::vector<std::string> vec;
vec.reserve(hosts.size());
for (const auto& host : hosts) {
vec.emplace_back(host);
}
return AddAxisCamera(name, vec);
}
WPI_UNIGNORE_DEPRECATED
} // namespace frc

View File

@@ -8,7 +8,6 @@
#include <functional>
#include <memory>
#include "cscore.h"
#include "cscore_cv.h"
#include "vision/VisionPipeline.h"
@@ -81,17 +80,35 @@ class VisionRunnerBase {
template <typename T>
class VisionRunner : public VisionRunnerBase {
public:
/**
* 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
*/
VisionRunner(cs::VideoSource videoSource, T* pipeline,
std::function<void(T&)> listener);
std::function<void(T&)> listener)
: VisionRunnerBase(videoSource),
m_pipeline(pipeline),
m_listener(listener) {}
virtual ~VisionRunner() = default;
protected:
void DoProcess(cv::Mat& image) override;
void DoProcess(cv::Mat& image) override {
m_pipeline->Process(image);
m_listener(*m_pipeline);
}
private:
T* m_pipeline;
std::function<void(T&)> m_listener;
};
} // namespace frc
#include "VisionRunner.inc"
} // namespace frc

View File

@@ -1,36 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <functional>
#include "vision/VisionRunner.h"
namespace frc {
/**
* 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
*/
template <typename T>
VisionRunner<T>::VisionRunner(cs::VideoSource videoSource, T* pipeline,
std::function<void(T&)> listener)
: VisionRunnerBase(videoSource),
m_pipeline(pipeline),
m_listener(listener) {}
template <typename T>
void VisionRunner<T>::DoProcess(cv::Mat& image) {
m_pipeline->Process(image);
m_listener(*m_pipeline);
}
} // namespace frc

File diff suppressed because it is too large Load Diff

View File

@@ -1,649 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_CSCORE_OO_INC_
#define CSCORE_CSCORE_OO_INC_
#include <functional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include <wpi/deprecated.h>
#include "cscore_oo.h"
namespace cs {
inline std::string VideoProperty::GetName() const {
m_status = 0;
return GetPropertyName(m_handle, &m_status);
}
inline int VideoProperty::Get() const {
m_status = 0;
return GetProperty(m_handle, &m_status);
}
inline void VideoProperty::Set(int value) {
m_status = 0;
SetProperty(m_handle, value, &m_status);
}
inline int VideoProperty::GetMin() const {
m_status = 0;
return GetPropertyMin(m_handle, &m_status);
}
inline int VideoProperty::GetMax() const {
m_status = 0;
return GetPropertyMax(m_handle, &m_status);
}
inline int VideoProperty::GetStep() const {
m_status = 0;
return GetPropertyStep(m_handle, &m_status);
}
inline int VideoProperty::GetDefault() const {
m_status = 0;
return GetPropertyDefault(m_handle, &m_status);
}
inline std::string VideoProperty::GetString() const {
m_status = 0;
return GetStringProperty(m_handle, &m_status);
}
inline std::string_view VideoProperty::GetString(
wpi::SmallVectorImpl<char>& buf) const {
m_status = 0;
return GetStringProperty(m_handle, buf, &m_status);
}
inline void VideoProperty::SetString(std::string_view value) {
m_status = 0;
SetStringProperty(m_handle, value, &m_status);
}
inline std::vector<std::string> VideoProperty::GetChoices() const {
m_status = 0;
return GetEnumPropertyChoices(m_handle, &m_status);
}
inline VideoProperty::VideoProperty(CS_Property handle) : m_handle(handle) {
m_status = 0;
if (handle == 0) {
m_kind = kNone;
} else {
m_kind =
static_cast<Kind>(static_cast<int>(GetPropertyKind(handle, &m_status)));
}
}
inline VideoProperty::VideoProperty(CS_Property handle, Kind kind)
: m_handle(handle), m_kind(kind) {}
inline VideoSource::VideoSource(const VideoSource& source)
: m_handle(source.m_handle == 0 ? 0
: CopySource(source.m_handle, &m_status)) {}
inline VideoSource::VideoSource(VideoSource&& other) noexcept : VideoSource() {
swap(*this, other);
}
inline VideoSource& VideoSource::operator=(VideoSource other) noexcept {
swap(*this, other);
return *this;
}
inline VideoSource::~VideoSource() {
m_status = 0;
if (m_handle != 0) {
ReleaseSource(m_handle, &m_status);
}
}
inline VideoSource::Kind VideoSource::GetKind() const {
m_status = 0;
return static_cast<VideoSource::Kind>(GetSourceKind(m_handle, &m_status));
}
inline std::string VideoSource::GetName() const {
m_status = 0;
return GetSourceName(m_handle, &m_status);
}
inline std::string VideoSource::GetDescription() const {
m_status = 0;
return GetSourceDescription(m_handle, &m_status);
}
inline uint64_t VideoSource::GetLastFrameTime() const {
m_status = 0;
return GetSourceLastFrameTime(m_handle, &m_status);
}
inline void VideoSource::SetConnectionStrategy(ConnectionStrategy strategy) {
m_status = 0;
SetSourceConnectionStrategy(
m_handle, static_cast<CS_ConnectionStrategy>(static_cast<int>(strategy)),
&m_status);
}
inline bool VideoSource::IsConnected() const {
m_status = 0;
return IsSourceConnected(m_handle, &m_status);
}
inline bool VideoSource::IsEnabled() const {
m_status = 0;
return IsSourceEnabled(m_handle, &m_status);
}
inline VideoProperty VideoSource::GetProperty(std::string_view name) {
m_status = 0;
return VideoProperty{GetSourceProperty(m_handle, name, &m_status)};
}
inline VideoMode VideoSource::GetVideoMode() const {
m_status = 0;
return GetSourceVideoMode(m_handle, &m_status);
}
inline bool VideoSource::SetVideoMode(const VideoMode& mode) {
m_status = 0;
return SetSourceVideoMode(m_handle, mode, &m_status);
}
inline bool VideoSource::SetVideoMode(VideoMode::PixelFormat pixelFormat,
int width, int height, int fps) {
m_status = 0;
return SetSourceVideoMode(
m_handle, VideoMode{pixelFormat, width, height, fps}, &m_status);
}
inline bool VideoSource::SetPixelFormat(VideoMode::PixelFormat pixelFormat) {
m_status = 0;
return SetSourcePixelFormat(m_handle, pixelFormat, &m_status);
}
inline bool VideoSource::SetResolution(int width, int height) {
m_status = 0;
return SetSourceResolution(m_handle, width, height, &m_status);
}
inline bool VideoSource::SetFPS(int fps) {
m_status = 0;
return SetSourceFPS(m_handle, fps, &m_status);
}
inline bool VideoSource::SetConfigJson(std::string_view config) {
m_status = 0;
return SetSourceConfigJson(m_handle, config, &m_status);
}
inline bool VideoSource::SetConfigJson(const wpi::json& config) {
m_status = 0;
return SetSourceConfigJson(m_handle, config, &m_status);
}
inline std::string VideoSource::GetConfigJson() const {
m_status = 0;
return GetSourceConfigJson(m_handle, &m_status);
}
inline double VideoSource::GetActualFPS() const {
m_status = 0;
return cs::GetTelemetryAverageValue(m_handle, CS_SOURCE_FRAMES_RECEIVED,
&m_status);
}
inline double VideoSource::GetActualDataRate() const {
m_status = 0;
return cs::GetTelemetryAverageValue(m_handle, CS_SOURCE_BYTES_RECEIVED,
&m_status);
}
inline std::vector<VideoMode> VideoSource::EnumerateVideoModes() const {
CS_Status status = 0;
return EnumerateSourceVideoModes(m_handle, &status);
}
inline void VideoCamera::SetBrightness(int brightness) {
m_status = 0;
SetCameraBrightness(m_handle, brightness, &m_status);
}
inline int VideoCamera::GetBrightness() {
m_status = 0;
return GetCameraBrightness(m_handle, &m_status);
}
inline void VideoCamera::SetWhiteBalanceAuto() {
m_status = 0;
SetCameraWhiteBalanceAuto(m_handle, &m_status);
}
inline void VideoCamera::SetWhiteBalanceHoldCurrent() {
m_status = 0;
SetCameraWhiteBalanceHoldCurrent(m_handle, &m_status);
}
inline void VideoCamera::SetWhiteBalanceManual(int value) {
m_status = 0;
SetCameraWhiteBalanceManual(m_handle, value, &m_status);
}
inline void VideoCamera::SetExposureAuto() {
m_status = 0;
SetCameraExposureAuto(m_handle, &m_status);
}
inline void VideoCamera::SetExposureHoldCurrent() {
m_status = 0;
SetCameraExposureHoldCurrent(m_handle, &m_status);
}
inline void VideoCamera::SetExposureManual(int value) {
m_status = 0;
SetCameraExposureManual(m_handle, value, &m_status);
}
inline UsbCamera::UsbCamera(std::string_view name, int dev) {
m_handle = CreateUsbCameraDev(name, dev, &m_status);
}
inline UsbCamera::UsbCamera(std::string_view name, std::string_view path) {
m_handle = CreateUsbCameraPath(name, path, &m_status);
}
inline std::vector<UsbCameraInfo> UsbCamera::EnumerateUsbCameras() {
CS_Status status = 0;
return ::cs::EnumerateUsbCameras(&status);
}
inline void UsbCamera::SetPath(std::string_view path) {
m_status = 0;
return ::cs::SetUsbCameraPath(m_handle, path, &m_status);
}
inline std::string UsbCamera::GetPath() const {
m_status = 0;
return ::cs::GetUsbCameraPath(m_handle, &m_status);
}
inline UsbCameraInfo UsbCamera::GetInfo() const {
m_status = 0;
return ::cs::GetUsbCameraInfo(m_handle, &m_status);
}
inline void UsbCamera::SetConnectVerbose(int level) {
m_status = 0;
SetProperty(GetSourceProperty(m_handle, "connect_verbose", &m_status), level,
&m_status);
}
inline HttpCamera::HttpCamera(std::string_view name, std::string_view url,
HttpCameraKind kind) {
m_handle = CreateHttpCamera(
name, url, static_cast<CS_HttpCameraKind>(static_cast<int>(kind)),
&m_status);
}
inline HttpCamera::HttpCamera(std::string_view name, const char* url,
HttpCameraKind kind) {
m_handle = CreateHttpCamera(
name, url, static_cast<CS_HttpCameraKind>(static_cast<int>(kind)),
&m_status);
}
inline HttpCamera::HttpCamera(std::string_view name, const std::string& url,
HttpCameraKind kind)
: HttpCamera(name, std::string_view{url}, kind) {}
inline HttpCamera::HttpCamera(std::string_view name,
std::span<const std::string> urls,
HttpCameraKind kind) {
m_handle = CreateHttpCamera(
name, urls, static_cast<CS_HttpCameraKind>(static_cast<int>(kind)),
&m_status);
}
template <typename T>
inline HttpCamera::HttpCamera(std::string_view name,
std::initializer_list<T> urls,
HttpCameraKind kind) {
std::vector<std::string> vec;
vec.reserve(urls.size());
for (const auto& url : urls) {
vec.emplace_back(url);
}
m_handle = CreateHttpCamera(
name, vec, static_cast<CS_HttpCameraKind>(static_cast<int>(kind)),
&m_status);
}
inline HttpCamera::HttpCameraKind HttpCamera::GetHttpCameraKind() const {
m_status = 0;
return static_cast<HttpCameraKind>(
static_cast<int>(::cs::GetHttpCameraKind(m_handle, &m_status)));
}
inline void HttpCamera::SetUrls(std::span<const std::string> urls) {
m_status = 0;
::cs::SetHttpCameraUrls(m_handle, urls, &m_status);
}
template <typename T>
inline void HttpCamera::SetUrls(std::initializer_list<T> urls) {
std::vector<std::string> vec;
vec.reserve(urls.size());
for (const auto& url : urls) {
vec.emplace_back(url);
}
m_status = 0;
::cs::SetHttpCameraUrls(m_handle, vec, &m_status);
}
inline std::vector<std::string> HttpCamera::GetUrls() const {
m_status = 0;
return ::cs::GetHttpCameraUrls(m_handle, &m_status);
}
WPI_IGNORE_DEPRECATED
inline std::vector<std::string> AxisCamera::HostToUrl(
std::span<const std::string> hosts) {
std::vector<std::string> rv;
rv.reserve(hosts.size());
for (const auto& host : hosts) {
rv.emplace_back(HostToUrl(std::string_view{host}));
}
return rv;
}
template <typename T>
inline std::vector<std::string> AxisCamera::HostToUrl(
std::initializer_list<T> hosts) {
std::vector<std::string> rv;
rv.reserve(hosts.size());
for (const auto& host : hosts) {
rv.emplace_back(HostToUrl(std::string_view{host}));
}
return rv;
}
inline AxisCamera::AxisCamera(std::string_view name, std::string_view host)
: HttpCamera(name, HostToUrl(host), kAxis) {}
inline AxisCamera::AxisCamera(std::string_view name, const char* host)
: HttpCamera(name, HostToUrl(host), kAxis) {}
inline AxisCamera::AxisCamera(std::string_view name, const std::string& host)
: HttpCamera(name, HostToUrl(std::string_view{host}), kAxis) {}
inline AxisCamera::AxisCamera(std::string_view name,
std::span<const std::string> hosts)
: HttpCamera(name, HostToUrl(hosts), kAxis) {}
template <typename T>
inline AxisCamera::AxisCamera(std::string_view name,
std::initializer_list<T> hosts)
: HttpCamera(name, HostToUrl(hosts), kAxis) {}
WPI_UNIGNORE_DEPRECATED
inline void ImageSource::NotifyError(std::string_view msg) {
m_status = 0;
NotifySourceError(m_handle, msg, &m_status);
}
inline void ImageSource::SetConnected(bool connected) {
m_status = 0;
SetSourceConnected(m_handle, connected, &m_status);
}
inline void ImageSource::SetDescription(std::string_view description) {
m_status = 0;
SetSourceDescription(m_handle, description, &m_status);
}
inline VideoProperty ImageSource::CreateProperty(std::string_view name,
VideoProperty::Kind kind,
int minimum, int maximum,
int step, int defaultValue,
int value) {
m_status = 0;
return VideoProperty{CreateSourceProperty(
m_handle, name, static_cast<CS_PropertyKind>(static_cast<int>(kind)),
minimum, maximum, step, defaultValue, value, &m_status)};
}
inline VideoProperty ImageSource::CreateIntegerProperty(std::string_view name,
int minimum,
int maximum, int step,
int defaultValue,
int value) {
m_status = 0;
return VideoProperty{CreateSourceProperty(
m_handle, name,
static_cast<CS_PropertyKind>(
static_cast<int>(VideoProperty::Kind::kInteger)),
minimum, maximum, step, defaultValue, value, &m_status)};
}
inline VideoProperty ImageSource::CreateBooleanProperty(std::string_view name,
bool defaultValue,
bool value) {
m_status = 0;
return VideoProperty{CreateSourceProperty(
m_handle, name,
static_cast<CS_PropertyKind>(
static_cast<int>(VideoProperty::Kind::kBoolean)),
0, 1, 1, defaultValue ? 1 : 0, value ? 1 : 0, &m_status)};
}
inline VideoProperty ImageSource::CreateStringProperty(std::string_view name,
std::string_view value) {
m_status = 0;
auto prop = VideoProperty{
CreateSourceProperty(m_handle, name,
static_cast<CS_PropertyKind>(
static_cast<int>(VideoProperty::Kind::kString)),
0, 0, 0, 0, 0, &m_status)};
prop.SetString(value);
return prop;
}
inline void ImageSource::SetEnumPropertyChoices(
const VideoProperty& property, std::span<const std::string> choices) {
m_status = 0;
SetSourceEnumPropertyChoices(m_handle, property.m_handle, choices, &m_status);
}
template <typename T>
inline void ImageSource::SetEnumPropertyChoices(
const VideoProperty& property, std::initializer_list<T> choices) {
std::vector<std::string> vec;
vec.reserve(choices.size());
for (const auto& choice : choices) {
vec.emplace_back(choice);
}
m_status = 0;
SetSourceEnumPropertyChoices(m_handle, property.m_handle, vec, &m_status);
}
inline VideoSink::VideoSink(const VideoSink& sink)
: m_handle(sink.m_handle == 0 ? 0 : CopySink(sink.m_handle, &m_status)) {}
inline VideoSink::VideoSink(VideoSink&& other) noexcept : VideoSink() {
swap(*this, other);
}
inline VideoSink& VideoSink::operator=(VideoSink other) noexcept {
swap(*this, other);
return *this;
}
inline VideoSink::~VideoSink() {
m_status = 0;
if (m_handle != 0) {
ReleaseSink(m_handle, &m_status);
}
}
inline VideoSink::Kind VideoSink::GetKind() const {
m_status = 0;
return static_cast<VideoSink::Kind>(GetSinkKind(m_handle, &m_status));
}
inline std::string VideoSink::GetName() const {
m_status = 0;
return GetSinkName(m_handle, &m_status);
}
inline std::string VideoSink::GetDescription() const {
m_status = 0;
return GetSinkDescription(m_handle, &m_status);
}
inline VideoProperty VideoSink::GetProperty(std::string_view name) {
m_status = 0;
return VideoProperty{GetSinkProperty(m_handle, name, &m_status)};
}
inline void VideoSink::SetSource(VideoSource source) {
m_status = 0;
if (!source) {
SetSinkSource(m_handle, 0, &m_status);
} else {
SetSinkSource(m_handle, source.m_handle, &m_status);
}
}
inline VideoSource VideoSink::GetSource() const {
m_status = 0;
auto handle = GetSinkSource(m_handle, &m_status);
return VideoSource{handle == 0 ? 0 : CopySource(handle, &m_status)};
}
inline VideoProperty VideoSink::GetSourceProperty(std::string_view name) {
m_status = 0;
return VideoProperty{GetSinkSourceProperty(m_handle, name, &m_status)};
}
inline bool VideoSink::SetConfigJson(std::string_view config) {
m_status = 0;
return SetSinkConfigJson(m_handle, config, &m_status);
}
inline bool VideoSink::SetConfigJson(const wpi::json& config) {
m_status = 0;
return SetSinkConfigJson(m_handle, config, &m_status);
}
inline std::string VideoSink::GetConfigJson() const {
m_status = 0;
return GetSinkConfigJson(m_handle, &m_status);
}
inline MjpegServer::MjpegServer(std::string_view name,
std::string_view listenAddress, int port) {
m_handle = CreateMjpegServer(name, listenAddress, port, &m_status);
}
inline std::string MjpegServer::GetListenAddress() const {
m_status = 0;
return cs::GetMjpegServerListenAddress(m_handle, &m_status);
}
inline int MjpegServer::GetPort() const {
m_status = 0;
return cs::GetMjpegServerPort(m_handle, &m_status);
}
inline void MjpegServer::SetResolution(int width, int height) {
m_status = 0;
SetProperty(GetSinkProperty(m_handle, "width", &m_status), width, &m_status);
SetProperty(GetSinkProperty(m_handle, "height", &m_status), height,
&m_status);
}
inline void MjpegServer::SetFPS(int fps) {
m_status = 0;
SetProperty(GetSinkProperty(m_handle, "fps", &m_status), fps, &m_status);
}
inline void MjpegServer::SetCompression(int quality) {
m_status = 0;
SetProperty(GetSinkProperty(m_handle, "compression", &m_status), quality,
&m_status);
}
inline void MjpegServer::SetDefaultCompression(int quality) {
m_status = 0;
SetProperty(GetSinkProperty(m_handle, "default_compression", &m_status),
quality, &m_status);
}
inline void ImageSink::SetDescription(std::string_view description) {
m_status = 0;
SetSinkDescription(m_handle, description, &m_status);
}
inline std::string ImageSink::GetError() const {
m_status = 0;
return GetSinkError(m_handle, &m_status);
}
inline void ImageSink::SetEnabled(bool enabled) {
m_status = 0;
SetSinkEnabled(m_handle, enabled, &m_status);
}
inline VideoSource VideoEvent::GetSource() const {
CS_Status status = 0;
return VideoSource{sourceHandle == 0 ? 0 : CopySource(sourceHandle, &status)};
}
inline VideoSink VideoEvent::GetSink() const {
CS_Status status = 0;
return VideoSink{sinkHandle == 0 ? 0 : CopySink(sinkHandle, &status)};
}
inline VideoProperty VideoEvent::GetProperty() const {
return VideoProperty{propertyHandle,
static_cast<VideoProperty::Kind>(propertyKind)};
}
inline VideoListener::VideoListener(
std::function<void(const VideoEvent& event)> callback, int eventMask,
bool immediateNotify) {
CS_Status status = 0;
m_handle = AddListener(
[=](const RawEvent& event) {
callback(static_cast<const VideoEvent&>(event));
},
eventMask, immediateNotify, &status);
}
inline VideoListener::VideoListener(VideoListener&& other) noexcept
: VideoListener() {
swap(*this, other);
}
inline VideoListener& VideoListener::operator=(VideoListener&& other) noexcept {
swap(*this, other);
return *this;
}
inline VideoListener::~VideoListener() {
CS_Status status = 0;
if (m_handle != 0) {
RemoveListener(m_handle, &status);
}
}
} // namespace cs
#endif // CSCORE_CSCORE_OO_INC_

View File

@@ -62,7 +62,10 @@ class Provider : public WindowManager {
* Perform global initialization. This should be called prior to
* wpi::gui::Initialize().
*/
void GlobalInit() override;
void GlobalInit() override {
WindowManager::GlobalInit();
wpi::gui::AddEarlyExecute([this] { Update(); });
}
/**
* Show the specified view by default on first load. Has no effect if
@@ -70,7 +73,17 @@ class Provider : public WindowManager {
*
* @param name View name
*/
void ShowDefault(std::string_view name);
void ShowDefault(std::string_view name) {
auto win = GetWindow(name);
if (win) {
return;
}
auto it = FindViewEntry(name);
if (it == m_viewEntries.end() || (*it)->name != name) {
return;
}
(*it)->showDefault = true;
}
/**
* Register a model and view combination. Equivalent to calling both
@@ -82,7 +95,10 @@ class Provider : public WindowManager {
* @param createView Functor for creating view
*/
void Register(std::string_view name, ExistsFunc exists,
CreateModelFunc createModel, CreateViewFunc createView);
CreateModelFunc createModel, CreateViewFunc createView) {
RegisterModel(name, std::move(exists), std::move(createModel));
RegisterView(name, name, nullptr, std::move(createView));
}
/**
* Register a model.
@@ -92,7 +108,16 @@ class Provider : public WindowManager {
* @param createModel Functor for creating model
*/
void RegisterModel(std::string_view name, ExistsFunc exists,
CreateModelFunc createModel);
CreateModelFunc createModel) {
auto it = FindModelEntry(name);
// ignore if exists
if (it != m_modelEntries.end() && (*it)->name == name) {
return;
}
// insert in sorted location
m_modelEntries.emplace(
it, MakeModelEntry(name, std::move(exists), std::move(createModel)));
}
/**
* Register a view.
@@ -103,10 +128,33 @@ class Provider : public WindowManager {
* @param createView Functor for creating view
*/
void RegisterView(std::string_view name, std::string_view modelName,
ViewExistsFunc exists, CreateViewFunc createView);
ViewExistsFunc exists, CreateViewFunc createView) {
// find model; if model doesn't exist, ignore
auto modelIt = FindModelEntry(modelName);
if (modelIt == m_modelEntries.end() || (*modelIt)->name != modelName) {
return;
}
auto viewIt = FindViewEntry(name);
// ignore if exists
if (viewIt != m_viewEntries.end() && (*viewIt)->name == name) {
return;
}
// insert in sorted location
m_viewEntries.emplace(viewIt,
MakeViewEntry(name, modelIt->get(), std::move(exists),
std::move(createView)));
}
protected:
virtual void Update();
virtual void Update() {
// update entries
for (auto&& entry : m_modelEntries) {
if (entry->model) {
entry->model->Update();
}
}
}
struct ModelEntry {
ModelEntry(std::string_view name, ExistsFunc exists,
@@ -145,8 +193,17 @@ class Provider : public WindowManager {
using ViewEntries = std::vector<std::unique_ptr<ViewEntry>>;
ViewEntries m_viewEntries;
typename ModelEntries::iterator FindModelEntry(std::string_view name);
typename ViewEntries::iterator FindViewEntry(std::string_view name);
typename ModelEntries::iterator FindModelEntry(std::string_view name) {
return std::lower_bound(
m_modelEntries.begin(), m_modelEntries.end(), name,
[](const auto& elem, std::string_view s) { return elem->name < s; });
}
typename ViewEntries::iterator FindViewEntry(std::string_view name) {
return std::lower_bound(
m_viewEntries.begin(), m_viewEntries.end(), name,
[](const auto& elem, std::string_view s) { return elem->name < s; });
}
virtual std::unique_ptr<ModelEntry> MakeModelEntry(
std::string_view name, ExistsFunc exists, CreateModelFunc createModel) {
@@ -166,5 +223,3 @@ class Provider : public WindowManager {
};
} // namespace glass
#include "Provider.inc"

View File

@@ -1,102 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <utility>
#include "glass/Provider.h"
namespace glass {
template <typename Functions>
void Provider<Functions>::GlobalInit() {
WindowManager::GlobalInit();
wpi::gui::AddEarlyExecute([this] { Update(); });
}
template <typename Functions>
void Provider<Functions>::ShowDefault(std::string_view name) {
auto win = GetWindow(name);
if (win) {
return;
}
auto it = FindViewEntry(name);
if (it == m_viewEntries.end() || (*it)->name != name) {
return;
}
(*it)->showDefault = true;
}
template <typename Functions>
void Provider<Functions>::Register(std::string_view name, ExistsFunc exists,
CreateModelFunc createModel,
CreateViewFunc createView) {
RegisterModel(name, std::move(exists), std::move(createModel));
RegisterView(name, name, nullptr, std::move(createView));
}
template <typename Functions>
void Provider<Functions>::RegisterModel(std::string_view name,
ExistsFunc exists,
CreateModelFunc createModel) {
auto it = FindModelEntry(name);
// ignore if exists
if (it != m_modelEntries.end() && (*it)->name == name) {
return;
}
// insert in sorted location
m_modelEntries.emplace(
it, MakeModelEntry(name, std::move(exists), std::move(createModel)));
}
template <typename Functions>
void Provider<Functions>::RegisterView(std::string_view name,
std::string_view modelName,
ViewExistsFunc exists,
CreateViewFunc createView) {
// find model; if model doesn't exist, ignore
auto modelIt = FindModelEntry(modelName);
if (modelIt == m_modelEntries.end() || (*modelIt)->name != modelName) {
return;
}
auto viewIt = FindViewEntry(name);
// ignore if exists
if (viewIt != m_viewEntries.end() && (*viewIt)->name == name) {
return;
}
// insert in sorted location
m_viewEntries.emplace(viewIt,
MakeViewEntry(name, modelIt->get(), std::move(exists),
std::move(createView)));
}
template <typename Functions>
void Provider<Functions>::Update() {
// update entries
for (auto&& entry : m_modelEntries) {
if (entry->model) {
entry->model->Update();
}
}
}
template <typename Functions>
typename Provider<Functions>::ModelEntries::iterator
Provider<Functions>::FindModelEntry(std::string_view name) {
return std::lower_bound(
m_modelEntries.begin(), m_modelEntries.end(), name,
[](const auto& elem, std::string_view s) { return elem->name < s; });
}
template <typename Functions>
typename Provider<Functions>::ViewEntries::iterator
Provider<Functions>::FindViewEntry(std::string_view name) {
return std::lower_bound(
m_viewEntries.begin(), m_viewEntries.end(), name,
[](const auto& elem, std::string_view s) { return elem->name < s; });
}
} // namespace glass

View File

@@ -6,9 +6,10 @@
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <fmt/format.h>
#include <hal/simulation/NotifyListener.h>
#include <wpi/json_fwd.h>
#include <wpi/mutex.h>
@@ -56,11 +57,19 @@ using WSRegisterFunc = std::function<void(
template <typename T>
void CreateProviders(std::string_view prefix, int32_t numChannels,
WSRegisterFunc webRegisterFunc);
WSRegisterFunc webRegisterFunc) {
for (int32_t i = 0; i < numChannels; i++) {
auto key = fmt::format("{}/{}", prefix, i);
auto ptr = std::make_unique<T>(i, key, prefix);
webRegisterFunc(key, std::move(ptr));
}
}
template <typename T>
void CreateSingleProvider(std::string_view key, WSRegisterFunc webRegisterFunc);
void CreateSingleProvider(std::string_view key,
WSRegisterFunc webRegisterFunc) {
auto ptr = std::make_unique<T>(key, key);
webRegisterFunc(key, std::move(ptr));
}
} // namespace wpilibws
#include "WSHalProviders.inc"

View File

@@ -1,34 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <memory>
#include <string_view>
#include <utility>
#include <fmt/format.h>
#include "WSHalProviders.h"
namespace wpilibws {
template <typename T>
void CreateProviders(std::string_view prefix, int numChannels,
WSRegisterFunc webRegisterFunc) {
for (int32_t i = 0; i < numChannels; i++) {
auto key = fmt::format("{}/{}", prefix, i);
auto ptr = std::make_unique<T>(i, key, prefix);
webRegisterFunc(key, std::move(ptr));
}
}
template <typename T>
void CreateSingleProvider(std::string_view key,
WSRegisterFunc webRegisterFunc) {
auto ptr = std::make_unique<T>(key, key);
webRegisterFunc(key, std::move(ptr));
}
} // namespace wpilibws

View File

@@ -3,6 +3,8 @@
// the WPILib BSD license file in the root directory of this project.
#include <functional>
#include <memory>
#include <utility>
#include <frc/Timer.h>
#include <frc/controller/HolonomicDriveController.h>
@@ -91,7 +93,15 @@ class SwerveControllerCommand
std::function<frc::Rotation2d()> desiredRotation,
std::function<void(std::array<frc::SwerveModuleState, NumModules>)>
output,
Requirements requirements = {});
Requirements requirements = {})
: m_trajectory(std::move(trajectory)),
m_pose(std::move(pose)),
m_kinematics(kinematics),
m_controller(xController, yController, thetaController),
m_desiredRotation(std::move(desiredRotation)),
m_outputStates(output) {
this->AddRequirements(requirements);
}
/**
* Constructs a new SwerveControllerCommand that when executed will follow the
@@ -129,7 +139,14 @@ class SwerveControllerCommand
frc::ProfiledPIDController<units::radians> thetaController,
std::function<void(std::array<frc::SwerveModuleState, NumModules>)>
output,
Requirements requirements = {});
Requirements requirements = {})
: m_trajectory(std::move(trajectory)),
m_pose(std::move(pose)),
m_kinematics(kinematics),
m_controller(xController, yController, thetaController),
m_outputStates(output) {
this->AddRequirements(requirements);
}
/**
* Constructs a new SwerveControllerCommand that when executed will follow the
@@ -159,7 +176,15 @@ class SwerveControllerCommand
std::function<frc::Rotation2d()> desiredRotation,
std::function<void(std::array<frc::SwerveModuleState, NumModules>)>
output,
Requirements requirements = {});
Requirements requirements = {})
: m_trajectory(std::move(trajectory)),
m_pose(std::move(pose)),
m_kinematics(kinematics),
m_controller(std::move(controller)),
m_desiredRotation(std::move(desiredRotation)),
m_outputStates(output) {
this->AddRequirements(requirements);
}
/**
* Constructs a new SwerveControllerCommand that when executed will follow the
@@ -191,15 +216,41 @@ class SwerveControllerCommand
frc::HolonomicDriveController controller,
std::function<void(std::array<frc::SwerveModuleState, NumModules>)>
output,
Requirements requirements = {});
Requirements requirements = {})
: m_trajectory(std::move(trajectory)),
m_pose(std::move(pose)),
m_kinematics(kinematics),
m_controller(std::move(controller)),
m_outputStates(output) {
this->AddRequirements(requirements);
}
void Initialize() override;
void Initialize() override {
if (m_desiredRotation == nullptr) {
m_desiredRotation = [&] {
return m_trajectory.States().back().pose.Rotation();
};
}
m_timer.Restart();
}
void Execute() override;
void Execute() override {
auto curTime = m_timer.Get();
auto m_desiredState = m_trajectory.Sample(curTime);
void End(bool interrupted) override;
auto targetChassisSpeeds =
m_controller.Calculate(m_pose(), m_desiredState, m_desiredRotation());
auto targetModuleStates =
m_kinematics.ToSwerveModuleStates(targetChassisSpeeds);
bool IsFinished() override;
m_outputStates(targetModuleStates);
}
void End(bool interrupted) override { m_timer.Stop(); }
bool IsFinished() override {
return m_timer.HasElapsed(m_trajectory.TotalTime());
}
private:
frc::Trajectory m_trajectory;
@@ -215,6 +266,5 @@ class SwerveControllerCommand
units::second_t m_prevTime;
frc::Rotation2d m_finalRotation;
};
} // namespace frc2
#include "SwerveControllerCommand.inc"
} // namespace frc2

View File

@@ -1,114 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <functional>
#include <memory>
#include <utility>
#include "frc2/command/SwerveControllerCommand.h"
namespace frc2 {
template <size_t NumModules>
SwerveControllerCommand<NumModules>::SwerveControllerCommand(
frc::Trajectory trajectory, std::function<frc::Pose2d()> pose,
frc::SwerveDriveKinematics<NumModules> kinematics,
frc::PIDController xController, frc::PIDController yController,
frc::ProfiledPIDController<units::radians> thetaController,
std::function<frc::Rotation2d()> desiredRotation,
std::function<void(std::array<frc::SwerveModuleState, NumModules>)> output,
Requirements requirements)
: m_trajectory(std::move(trajectory)),
m_pose(std::move(pose)),
m_kinematics(kinematics),
m_controller(xController, yController, thetaController),
m_desiredRotation(std::move(desiredRotation)),
m_outputStates(output) {
this->AddRequirements(requirements);
}
template <size_t NumModules>
SwerveControllerCommand<NumModules>::SwerveControllerCommand(
frc::Trajectory trajectory, std::function<frc::Pose2d()> pose,
frc::SwerveDriveKinematics<NumModules> kinematics,
frc::PIDController xController, frc::PIDController yController,
frc::ProfiledPIDController<units::radians> thetaController,
std::function<void(std::array<frc::SwerveModuleState, NumModules>)> output,
Requirements requirements)
: m_trajectory(std::move(trajectory)),
m_pose(std::move(pose)),
m_kinematics(kinematics),
m_controller(xController, yController, thetaController),
m_outputStates(output) {
this->AddRequirements(requirements);
}
template <size_t NumModules>
SwerveControllerCommand<NumModules>::SwerveControllerCommand(
frc::Trajectory trajectory, std::function<frc::Pose2d()> pose,
frc::SwerveDriveKinematics<NumModules> kinematics,
frc::HolonomicDriveController controller,
std::function<frc::Rotation2d()> desiredRotation,
std::function<void(std::array<frc::SwerveModuleState, NumModules>)> output,
Requirements requirements)
: m_trajectory(std::move(trajectory)),
m_pose(std::move(pose)),
m_kinematics(kinematics),
m_controller(std::move(controller)),
m_desiredRotation(std::move(desiredRotation)),
m_outputStates(output) {
this->AddRequirements(requirements);
}
template <size_t NumModules>
SwerveControllerCommand<NumModules>::SwerveControllerCommand(
frc::Trajectory trajectory, std::function<frc::Pose2d()> pose,
frc::SwerveDriveKinematics<NumModules> kinematics,
frc::HolonomicDriveController controller,
std::function<void(std::array<frc::SwerveModuleState, NumModules>)> output,
Requirements requirements)
: m_trajectory(std::move(trajectory)),
m_pose(std::move(pose)),
m_kinematics(kinematics),
m_controller(std::move(controller)),
m_outputStates(output) {
this->AddRequirements(requirements);
}
template <size_t NumModules>
void SwerveControllerCommand<NumModules>::Initialize() {
if (m_desiredRotation == nullptr) {
m_desiredRotation = [&] {
return m_trajectory.States().back().pose.Rotation();
};
}
m_timer.Restart();
}
template <size_t NumModules>
void SwerveControllerCommand<NumModules>::Execute() {
auto curTime = m_timer.Get();
auto m_desiredState = m_trajectory.Sample(curTime);
auto targetChassisSpeeds =
m_controller.Calculate(m_pose(), m_desiredState, m_desiredRotation());
auto targetModuleStates =
m_kinematics.ToSwerveModuleStates(targetChassisSpeeds);
m_outputStates(targetModuleStates);
}
template <size_t NumModules>
void SwerveControllerCommand<NumModules>::End(bool interrupted) {
m_timer.Stop();
}
template <size_t NumModules>
bool SwerveControllerCommand<NumModules>::IsFinished() {
return m_timer.HasElapsed(m_trajectory.TotalTime());
}
} // namespace frc2

View File

@@ -36,7 +36,11 @@ class [[deprecated(
*/
template <class... MotorControllers>
explicit MotorControllerGroup(MotorController& motorController,
MotorControllers&... motorControllers);
MotorControllers&... motorControllers)
: m_motorControllers(std::vector<std::reference_wrapper<MotorController>>{
motorController, motorControllers...}) {
Initialize();
}
/**
* Create a new MotorControllerGroup with the provided MotorControllers.
@@ -68,6 +72,4 @@ class [[deprecated(
} // namespace frc
#include "frc/motorcontrol/MotorControllerGroup.inc"
WPI_UNIGNORE_DEPRECATED

View File

@@ -1,22 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <functional>
#include <vector>
#include "frc/motorcontrol/MotorControllerGroup.h"
namespace frc {
template <class... MotorControllers>
MotorControllerGroup::MotorControllerGroup(
MotorController& motorController, MotorControllers&... motorControllers)
: m_motorControllers(std::vector<std::reference_wrapper<MotorController>>{
motorController, motorControllers...}) {
Initialize();
}
} // namespace frc

View File

@@ -4,8 +4,6 @@
#pragma once
#include <memory>
#include <string>
#include <string_view>
#include <networktables/NetworkTable.h>
@@ -34,7 +32,9 @@ class ShuffleboardComponent : public ShuffleboardComponentBase {
* @param type The component type.
*/
ShuffleboardComponent(ShuffleboardContainer& parent, std::string_view title,
std::string_view type = "");
std::string_view type = "")
: ShuffleboardValue(title),
ShuffleboardComponentBase(parent, title, type) {}
/**
* Sets custom properties for this component. Property names are
@@ -44,7 +44,11 @@ class ShuffleboardComponent : public ShuffleboardComponentBase {
* @param properties the properties for this component
* @return this component
*/
Derived& WithProperties(const wpi::StringMap<nt::Value>& properties);
Derived& WithProperties(const wpi::StringMap<nt::Value>& properties) {
m_properties = properties;
m_metadataDirty = true;
return *static_cast<Derived*>(this);
}
/**
* Sets the position of this component in the tab. This has no effect if this
@@ -59,7 +63,12 @@ class ShuffleboardComponent : public ShuffleboardComponentBase {
* @param rowIndex the row in the tab to place this component
* @return this component
*/
Derived& WithPosition(int columnIndex, int rowIndex);
Derived& WithPosition(int columnIndex, int rowIndex) {
m_column = columnIndex;
m_row = rowIndex;
m_metadataDirty = true;
return *static_cast<Derived*>(this);
}
/**
* Sets the size of this component in the tab. This has no effect if this
@@ -69,9 +78,12 @@ class ShuffleboardComponent : public ShuffleboardComponentBase {
* @param height how many rows high the component should be
* @return this component
*/
Derived& WithSize(int width, int height);
Derived& WithSize(int width, int height) {
m_width = width;
m_height = height;
m_metadataDirty = true;
return *static_cast<Derived*>(this);
}
};
} // namespace frc
#include "frc/shuffleboard/ShuffleboardComponent.inc"

View File

@@ -1,47 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <memory>
#include <string>
#include <string_view>
#include "frc/shuffleboard/ShuffleboardComponent.h"
namespace frc {
template <typename Derived>
ShuffleboardComponent<Derived>::ShuffleboardComponent(
ShuffleboardContainer& parent, std::string_view title,
std::string_view type)
: ShuffleboardValue(title),
ShuffleboardComponentBase(parent, title, type) {}
template <typename Derived>
Derived& ShuffleboardComponent<Derived>::WithProperties(
const wpi::StringMap<nt::Value>& properties) {
m_properties = properties;
m_metadataDirty = true;
return *static_cast<Derived*>(this);
}
template <typename Derived>
Derived& ShuffleboardComponent<Derived>::WithPosition(int columnIndex,
int rowIndex) {
m_column = columnIndex;
m_row = rowIndex;
m_metadataDirty = true;
return *static_cast<Derived*>(this);
}
template <typename Derived>
Derived& ShuffleboardComponent<Derived>::WithSize(int width, int height) {
m_width = width;
m_height = height;
m_metadataDirty = true;
return *static_cast<Derived*>(this);
}
} // namespace frc

View File

@@ -14,7 +14,6 @@
#include <networktables/NetworkTable.h>
#include "frc/shuffleboard/ShuffleboardComponent.h"
#include "frc/shuffleboard/ShuffleboardComponent.inc"
#include "frc/shuffleboard/ShuffleboardComponentBase.h"
#include "frc/shuffleboard/ShuffleboardWidget.h"

View File

@@ -4,12 +4,17 @@
#pragma once
#include <algorithm>
#include <concepts>
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include <wpi/StringMap.h>
#include <wpi/sendable/SendableBuilder.h>
#include "frc/smartdashboard/SendableChooserBase.h"
@@ -34,10 +39,14 @@ class SendableChooser : public SendableChooserBase {
wpi::StringMap<T> m_choices;
std::function<void(T)> m_listener;
template <class U>
static U _unwrap_smart_ptr(const U& value);
static U _unwrap_smart_ptr(const U& value) {
return value;
}
template <class U>
static std::weak_ptr<U> _unwrap_smart_ptr(const std::shared_ptr<U>& value);
static std::weak_ptr<U> _unwrap_smart_ptr(const std::shared_ptr<U>& value) {
return value;
}
public:
using CopyType = decltype(_unwrap_smart_ptr(m_choices.lookup("")));
@@ -56,7 +65,9 @@ class SendableChooser : public SendableChooserBase {
* @param name the name of the option
* @param object the option
*/
void AddOption(std::string_view name, T object);
void AddOption(std::string_view name, T object) {
m_choices[name] = std::move(object);
}
/**
* Add the given object to the list of options and marks it as the default.
@@ -67,7 +78,10 @@ class SendableChooser : public SendableChooserBase {
* @param name the name of the option
* @param object the option
*/
void SetDefaultOption(std::string_view name, T object);
void SetDefaultOption(std::string_view name, T object) {
m_defaultChoice = name;
AddOption(name, std::move(object));
}
/**
* Returns a copy of the selected option (a std::weak_ptr<U> if T =
@@ -80,7 +94,20 @@ class SendableChooser : public SendableChooserBase {
*
* @return The option selected
*/
CopyType GetSelected() const;
CopyType GetSelected() const {
std::string selected = m_defaultChoice;
{
std::scoped_lock lock(m_mutex);
if (m_haveSelected) {
selected = m_selected;
}
}
if (selected.empty()) {
return CopyType{};
} else {
return _unwrap_smart_ptr(m_choices.lookup(selected));
}
}
/**
* Bind a listener that's called when the selected value changes.
@@ -88,11 +115,66 @@ class SendableChooser : public SendableChooserBase {
* previous listener.
* @param listener The function to call that accepts the new value
*/
void OnChange(std::function<void(T)>);
void OnChange(std::function<void(T)> listener) {
std::scoped_lock lock(m_mutex);
m_listener = listener;
}
void InitSendable(wpi::SendableBuilder& builder) override;
void InitSendable(wpi::SendableBuilder& builder) override {
builder.SetSmartDashboardType("String Chooser");
builder.PublishConstInteger(kInstance, m_instance);
builder.AddStringArrayProperty(
kOptions,
[=, this] {
std::vector<std::string> keys;
for (const auto& choice : m_choices) {
keys.emplace_back(choice.first());
}
// Unlike std::map, wpi::StringMap elements
// are not sorted
std::sort(keys.begin(), keys.end());
return keys;
},
nullptr);
builder.AddSmallStringProperty(
kDefault,
[=, this](wpi::SmallVectorImpl<char>&) -> std::string_view {
return m_defaultChoice;
},
nullptr);
builder.AddSmallStringProperty(
kActive,
[=, this](wpi::SmallVectorImpl<char>& buf) -> std::string_view {
std::scoped_lock lock(m_mutex);
if (m_haveSelected) {
buf.assign(m_selected.begin(), m_selected.end());
return {buf.data(), buf.size()};
} else {
return m_defaultChoice;
}
},
nullptr);
builder.AddStringProperty(kSelected, nullptr,
[=, this](std::string_view val) {
T choice{};
std::function<void(T)> listener;
{
std::scoped_lock lock(m_mutex);
m_haveSelected = true;
m_selected = val;
if (m_previousVal != val && m_listener) {
choice = m_choices[val];
listener = m_listener;
}
m_previousVal = val;
}
if (listener) {
listener(choice);
}
});
}
};
} // namespace frc
#include "frc/smartdashboard/SendableChooser.inc"

View File

@@ -1,131 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <algorithm>
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include <wpi/sendable/SendableBuilder.h>
#include "frc/smartdashboard/SendableChooser.h"
namespace frc {
template <class T>
requires std::copy_constructible<T> && std::default_initializable<T>
void SendableChooser<T>::AddOption(std::string_view name, T object) {
m_choices[name] = std::move(object);
}
template <class T>
requires std::copy_constructible<T> && std::default_initializable<T>
void SendableChooser<T>::SetDefaultOption(std::string_view name, T object) {
m_defaultChoice = name;
AddOption(name, std::move(object));
}
template <class T>
requires std::copy_constructible<T> && std::default_initializable<T>
typename SendableChooser<T>::CopyType SendableChooser<T>::GetSelected() const {
std::string selected = m_defaultChoice;
{
std::scoped_lock lock(m_mutex);
if (m_haveSelected) {
selected = m_selected;
}
}
if (selected.empty()) {
return CopyType{};
} else {
return _unwrap_smart_ptr(m_choices.lookup(selected));
}
}
template <class T>
requires std::copy_constructible<T> && std::default_initializable<T>
void SendableChooser<T>::OnChange(std::function<void(T)> listener) {
std::scoped_lock lock(m_mutex);
m_listener = listener;
}
template <class T>
requires std::copy_constructible<T> && std::default_initializable<T>
void SendableChooser<T>::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("String Chooser");
builder.PublishConstInteger(kInstance, m_instance);
builder.AddStringArrayProperty(
kOptions,
[=, this] {
std::vector<std::string> keys;
for (const auto& choice : m_choices) {
keys.emplace_back(choice.first());
}
// Unlike std::map, wpi::StringMap elements
// are not sorted
std::sort(keys.begin(), keys.end());
return keys;
},
nullptr);
builder.AddSmallStringProperty(
kDefault,
[=, this](wpi::SmallVectorImpl<char>&) -> std::string_view {
return m_defaultChoice;
},
nullptr);
builder.AddSmallStringProperty(
kActive,
[=, this](wpi::SmallVectorImpl<char>& buf) -> std::string_view {
std::scoped_lock lock(m_mutex);
if (m_haveSelected) {
buf.assign(m_selected.begin(), m_selected.end());
return {buf.data(), buf.size()};
} else {
return m_defaultChoice;
}
},
nullptr);
builder.AddStringProperty(kSelected, nullptr,
[=, this](std::string_view val) {
T choice{};
std::function<void(T)> listener;
{
std::scoped_lock lock(m_mutex);
m_haveSelected = true;
m_selected = val;
if (m_previousVal != val && m_listener) {
choice = m_choices[val];
listener = m_listener;
}
m_previousVal = val;
}
if (listener) {
listener(choice);
}
});
}
template <class T>
requires std::copy_constructible<T> && std::default_initializable<T>
template <class U>
U SendableChooser<T>::_unwrap_smart_ptr(const U& value) {
return value;
}
template <class T>
requires std::copy_constructible<T> && std::default_initializable<T>
template <class U>
std::weak_ptr<U> SendableChooser<T>::_unwrap_smart_ptr(
const std::shared_ptr<U>& value) {
return value;
}
} // namespace frc

View File

@@ -316,7 +316,18 @@ class HttpRequest {
}
template <typename T>
HttpRequest(const HttpLocation& loc, const T& extraParams);
HttpRequest(const HttpLocation& loc, const T& extraParams)
: host{loc.host}, port{loc.port} {
StringMap<std::string_view> params;
for (const auto& p : loc.params) {
params.insert(std::make_pair(GetFirst(p), GetSecond(p)));
}
for (const auto& p : extraParams) {
params.insert(std::make_pair(GetFirst(p), GetSecond(p)));
}
SetPath(loc.path, params);
SetAuth(loc);
}
HttpRequest(const HttpLocation& loc, std::string_view path_)
: host{loc.host}, port{loc.port}, path{path_} {
@@ -337,8 +348,27 @@ class HttpRequest {
private:
void SetAuth(const HttpLocation& loc);
template <typename T>
void SetPath(std::string_view path_, const T& params);
void SetPath(std::string_view path_, const T& params) {
// Build location including query string
raw_svector_ostream pathOs{path};
pathOs << path_;
bool first = true;
for (const auto& param : params) {
if (first) {
pathOs << '?';
first = false;
} else {
pathOs << '&';
}
SmallString<64> escapeBuf;
pathOs << EscapeURI(GetFirst(param), escapeBuf, false);
if (!GetSecond(param).empty()) {
pathOs << '=' << EscapeURI(GetSecond(param), escapeBuf, false);
}
}
}
template <typename T>
static std::string_view GetFirst(const T& elem) {
@@ -416,8 +446,10 @@ class HttpMultipartScanner {
std::string m_buf;
};
inline HttpPathRef HttpPath::drop_front(size_t n) const {
return HttpPathRef(*this, n);
}
} // namespace wpi
#include "HttpUtil.inc"
#endif // WPINET_HTTPUTIL_H_

View File

@@ -1,55 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#ifndef WPINET_HTTPUTIL_INC_
#define WPINET_HTTPUTIL_INC_
#include <utility>
#include "wpinet/HttpUtil.h"
namespace wpi {
inline HttpPathRef HttpPath::drop_front(size_t n) const {
return HttpPathRef(*this, n);
}
template <typename T>
HttpRequest::HttpRequest(const HttpLocation& loc, const T& extraParams)
: host{loc.host}, port{loc.port} {
StringMap<std::string_view> params;
for (const auto& p : loc.params) {
params.insert(std::make_pair(GetFirst(p), GetSecond(p)));
}
for (const auto& p : extraParams) {
params.insert(std::make_pair(GetFirst(p), GetSecond(p)));
}
SetPath(loc.path, params);
SetAuth(loc);
}
template <typename T>
void HttpRequest::SetPath(std::string_view path_, const T& params) {
// Build location including query string
raw_svector_ostream pathOs{path};
pathOs << path_;
bool first = true;
for (const auto& param : params) {
if (first) {
pathOs << '?';
first = false;
} else {
pathOs << '&';
}
SmallString<64> escapeBuf;
pathOs << EscapeURI(GetFirst(param), escapeBuf, false);
if (!GetSecond(param).empty()) {
pathOs << '=' << EscapeURI(GetSecond(param), escapeBuf, false);
}
}
}
} // namespace wpi
#endif // WPINET_HTTPUTIL_INC_

View File

@@ -37,7 +37,43 @@ class HttpWebSocketServerConnection
* @param protocols Acceptable subprotocols
*/
HttpWebSocketServerConnection(std::shared_ptr<uv::Stream> stream,
std::span<const std::string_view> protocols);
std::span<const std::string_view> protocols)
: HttpServerConnection{stream},
m_helper{m_request},
m_protocols{protocols.begin(), protocols.end()} {
// Handle upgrade event
m_helper.upgrade.connect([this] {
// Negotiate sub-protocol
SmallVector<std::string_view, 2> protocols{m_protocols.begin(),
m_protocols.end()};
std::string_view protocol = m_helper.MatchProtocol(protocols).second;
// Check that the upgrade is valid
if (!IsValidWsUpgrade(protocol)) {
return;
}
// Disconnect HttpServerConnection header reader
m_dataConn.disconnect();
m_messageCompleteConn.disconnect();
// Accepting the stream may destroy this (as it replaces the stream user
// data), so grab a shared pointer first.
auto self = this->shared_from_this();
// Accept the upgrade
auto ws = m_helper.Accept(m_stream, protocol);
// Set this as the websocket user data to keep it around
ws->SetData(self);
// Store in member
m_websocket = ws.get();
// Call derived class function
ProcessWsUpgrade();
});
}
/**
* Constructor.
@@ -88,6 +124,4 @@ class HttpWebSocketServerConnection
} // namespace wpi
#include "HttpWebSocketServerConnection.inc"
#endif // WPINET_HTTPWEBSOCKETSERVERCONNECTION_H_

View File

@@ -1,57 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#ifndef WPINET_HTTPWEBSOCKETSERVERCONNECTION_INC_
#define WPINET_HTTPWEBSOCKETSERVERCONNECTION_INC_
#include <memory>
#include "wpinet/HttpWebSocketServerConnection.h"
namespace wpi {
template <typename Derived>
HttpWebSocketServerConnection<Derived>::HttpWebSocketServerConnection(
std::shared_ptr<uv::Stream> stream,
std::span<const std::string_view> protocols)
: HttpServerConnection{stream},
m_helper{m_request},
m_protocols{protocols.begin(), protocols.end()} {
// Handle upgrade event
m_helper.upgrade.connect([this] {
// Negotiate sub-protocol
SmallVector<std::string_view, 2> protocols{m_protocols.begin(),
m_protocols.end()};
std::string_view protocol = m_helper.MatchProtocol(protocols).second;
// Check that the upgrade is valid
if (!IsValidWsUpgrade(protocol)) {
return;
}
// Disconnect HttpServerConnection header reader
m_dataConn.disconnect();
m_messageCompleteConn.disconnect();
// Accepting the stream may destroy this (as it replaces the stream user
// data), so grab a shared pointer first.
auto self = this->shared_from_this();
// Accept the upgrade
auto ws = m_helper.Accept(m_stream, protocol);
// Set this as the websocket user data to keep it around
ws->SetData(self);
// Store in member
m_websocket = ws.get();
// Call derived class function
ProcessWsUpgrade();
});
}
} // namespace wpi
#endif // WPINET_HTTPWEBSOCKETSERVERCONNECTION_INC_

View File

@@ -242,7 +242,54 @@ class circular_buffer {
/**
* Resizes internal buffer to given size.
*/
void resize(size_t size);
void resize(size_t size) {
if (size > m_data.size()) {
// Find end of buffer
size_t insertLocation = (m_front + m_length) % m_data.size();
// If insertion location precedes front of buffer, push front index back
if (insertLocation <= m_front) {
m_front += size - m_data.size();
}
// Add elements to end of buffer
m_data.insert(m_data.begin() + insertLocation, size - m_data.size(), 0);
} else if (size < m_data.size()) {
/* 1) Shift element block start at "front" left as many blocks as were
* removed up to but not exceeding buffer[0]
* 2) Shrink buffer, which will remove even more elements automatically if
* necessary
*/
size_t elemsToRemove = m_data.size() - size;
auto frontIter = m_data.begin() + m_front;
if (m_front < elemsToRemove) {
/* Remove elements from end of buffer before shifting start of element
* block. Doing so saves a few copies.
*/
m_data.erase(frontIter + size, m_data.end());
// Shift start of element block to left
m_data.erase(m_data.begin(), frontIter);
// Update metadata
m_front = 0;
} else {
// Shift start of element block to left
m_data.erase(frontIter - elemsToRemove, frontIter);
// Update metadata
m_front -= elemsToRemove;
}
/* Length only changes during a shrink if all unused spaces have been
* removed. Length decreases as used spaces are removed to meet the
* required size.
*/
if (m_length > size) {
m_length = size;
}
}
}
/**
* Empties internal buffer.
@@ -299,5 +346,3 @@ class circular_buffer {
};
} // namespace wpi
#include "wpi/circular_buffer.inc"

View File

@@ -1,64 +0,0 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include "wpi/circular_buffer.h"
namespace wpi {
/**
* Resizes internal buffer to given size.
*/
template <class T>
void circular_buffer<T>::resize(size_t size) {
if (size > m_data.size()) {
// Find end of buffer
size_t insertLocation = (m_front + m_length) % m_data.size();
// If insertion location precedes front of buffer, push front index back
if (insertLocation <= m_front) {
m_front += size - m_data.size();
}
// Add elements to end of buffer
m_data.insert(m_data.begin() + insertLocation, size - m_data.size(), 0);
} else if (size < m_data.size()) {
/* 1) Shift element block start at "front" left as many blocks as were
* removed up to but not exceeding buffer[0]
* 2) Shrink buffer, which will remove even more elements automatically if
* necessary
*/
size_t elemsToRemove = m_data.size() - size;
auto frontIter = m_data.begin() + m_front;
if (m_front < elemsToRemove) {
/* Remove elements from end of buffer before shifting start of element
* block. Doing so saves a few copies.
*/
m_data.erase(frontIter + size, m_data.end());
// Shift start of element block to left
m_data.erase(m_data.begin(), frontIter);
// Update metadata
m_front = 0;
} else {
// Shift start of element block to left
m_data.erase(frontIter - elemsToRemove, frontIter);
// Update metadata
m_front -= elemsToRemove;
}
/* Length only changes during a shrink if all unused spaces have been
* removed. Length decreases as used spaces are removed to meet the
* required size.
*/
if (m_length > size) {
m_length = size;
}
}
}
} // namespace wpi