mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
Merge .inc files into headers (#7215)
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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_
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
|
||||
@@ -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_
|
||||
@@ -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_
|
||||
|
||||
@@ -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_
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user