diff --git a/cameraserver/src/main/native/include/cameraserver/CameraServer.h b/cameraserver/src/main/native/include/cameraserver/CameraServer.h index 0dfa97f178a..68f37f22b05 100644 --- a/cameraserver/src/main/native/include/cameraserver/CameraServer.h +++ b/cameraserver/src/main/native/include/cameraserver/CameraServer.h @@ -9,10 +9,10 @@ #include #include #include +#include #include -#include "cscore.h" #include "cscore_cv.h" namespace frc { @@ -130,7 +130,9 @@ class CameraServer { */ template [[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]] - static cs::AxisCamera AddAxisCamera(std::initializer_list hosts); + static cs::AxisCamera AddAxisCamera(std::initializer_list hosts) { + return AddAxisCamera("Axis Camera", hosts); + } /** * Adds an Axis IP camera. @@ -185,7 +187,14 @@ class CameraServer { template [[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]] static cs::AxisCamera AddAxisCamera(std::string_view name, - std::initializer_list hosts); + std::initializer_list hosts) { + std::vector 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" diff --git a/cameraserver/src/main/native/include/cameraserver/CameraServer.inc b/cameraserver/src/main/native/include/cameraserver/CameraServer.inc deleted file mode 100644 index 5ae14f7f9a9..00000000000 --- a/cameraserver/src/main/native/include/cameraserver/CameraServer.inc +++ /dev/null @@ -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 -#include - -#include "cameraserver/CameraServer.h" - -namespace frc { - -WPI_IGNORE_DEPRECATED -template -inline cs::AxisCamera CameraServer::AddAxisCamera( - std::initializer_list hosts) { - return AddAxisCamera("Axis Camera", hosts); -} - -template -inline cs::AxisCamera CameraServer::AddAxisCamera( - std::string_view name, std::initializer_list hosts) { - std::vector vec; - vec.reserve(hosts.size()); - for (const auto& host : hosts) { - vec.emplace_back(host); - } - return AddAxisCamera(name, vec); -} -WPI_UNIGNORE_DEPRECATED - -} // namespace frc diff --git a/cameraserver/src/main/native/include/vision/VisionRunner.h b/cameraserver/src/main/native/include/vision/VisionRunner.h index 6e6e93adfab..750d15797a3 100644 --- a/cameraserver/src/main/native/include/vision/VisionRunner.h +++ b/cameraserver/src/main/native/include/vision/VisionRunner.h @@ -8,7 +8,6 @@ #include #include -#include "cscore.h" #include "cscore_cv.h" #include "vision/VisionPipeline.h" @@ -81,17 +80,35 @@ class VisionRunnerBase { template 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 listener); + std::function 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 m_listener; }; -} // namespace frc -#include "VisionRunner.inc" +} // namespace frc diff --git a/cameraserver/src/main/native/include/vision/VisionRunner.inc b/cameraserver/src/main/native/include/vision/VisionRunner.inc deleted file mode 100644 index 56cfe695e40..00000000000 --- a/cameraserver/src/main/native/include/vision/VisionRunner.inc +++ /dev/null @@ -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 - -#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 -VisionRunner::VisionRunner(cs::VideoSource videoSource, T* pipeline, - std::function listener) - : VisionRunnerBase(videoSource), - m_pipeline(pipeline), - m_listener(listener) {} - -template -void VisionRunner::DoProcess(cv::Mat& image) { - m_pipeline->Process(image); - m_listener(*m_pipeline); -} - -} // namespace frc diff --git a/cscore/src/main/native/include/cscore_oo.h b/cscore/src/main/native/include/cscore_oo.h index 8fb8f4be32f..2c6d64171af 100644 --- a/cscore/src/main/native/include/cscore_oo.h +++ b/cscore/src/main/native/include/cscore_oo.h @@ -13,6 +13,8 @@ #include #include +#include + #include "cscore_cpp.h" namespace cs { @@ -63,7 +65,10 @@ class VideoProperty { * * @return Property name. */ - std::string GetName() const; + std::string GetName() const { + m_status = 0; + return GetPropertyName(m_handle, &m_status); + } /** * Returns property kind. @@ -112,42 +117,60 @@ class VideoProperty { * * @return Property value. */ - int Get() const; + int Get() const { + m_status = 0; + return GetProperty(m_handle, &m_status); + } /** * Sets property value. * * @param value Property value. */ - void Set(int value); + void Set(int value) { + m_status = 0; + SetProperty(m_handle, value, &m_status); + } /** * Returns property minimum value. * * @return Property minimum value. */ - int GetMin() const; + int GetMin() const { + m_status = 0; + return GetPropertyMin(m_handle, &m_status); + } /** * Returns property maximum value. * * @return Property maximum value. */ - int GetMax() const; + int GetMax() const { + m_status = 0; + return GetPropertyMax(m_handle, &m_status); + } /** * Returns property step size. * * @return Property step size. */ - int GetStep() const; + int GetStep() const { + m_status = 0; + return GetPropertyStep(m_handle, &m_status); + } /** * Returns property default value. * * @return Property default value. */ - int GetDefault() const; + int GetDefault() const { + m_status = 0; + return GetPropertyDefault(m_handle, &m_status); + } /** * Returns the string property value. @@ -156,7 +179,10 @@ class VideoProperty { * * @return The string property value. */ - std::string GetString() const; + std::string GetString() const { + m_status = 0; + return GetStringProperty(m_handle, &m_status); + } /** * Returns the string property value as a reference to the given buffer. @@ -166,7 +192,10 @@ class VideoProperty { * @param buf The backing storage to which to write the property value. * @return The string property value as a reference to the given buffer. */ - std::string_view GetString(wpi::SmallVectorImpl& buf) const; + std::string_view GetString(wpi::SmallVectorImpl& buf) const { + m_status = 0; + return GetStringProperty(m_handle, buf, &m_status); + } /** * Sets the string property value. @@ -175,7 +204,10 @@ class VideoProperty { * * @param value String property value. */ - void SetString(std::string_view value); + void SetString(std::string_view value) { + m_status = 0; + SetStringProperty(m_handle, value, &m_status); + } /** * Returns the possible values for the enum property value. @@ -184,7 +216,10 @@ class VideoProperty { * * @return The possible values for the enum property value. */ - std::vector GetChoices() const; + std::vector GetChoices() const { + m_status = 0; + return GetEnumPropertyChoices(m_handle, &m_status); + } /** * Returns the last status. @@ -194,8 +229,18 @@ class VideoProperty { CS_Status GetLastStatus() const { return m_status; } private: - explicit VideoProperty(CS_Property handle); - VideoProperty(CS_Property handle, Kind kind); + explicit VideoProperty(CS_Property handle) { + m_status = 0; + if (handle == 0) { + m_kind = kNone; + } else { + m_kind = static_cast( + static_cast(GetPropertyKind(handle, &m_status))); + } + } + + VideoProperty(CS_Property handle, Kind kind) + : m_handle(handle), m_kind(kind) {} mutable CS_Status m_status{0}; CS_Property m_handle{0}; @@ -248,10 +293,27 @@ class VideoSource { }; VideoSource() noexcept = default; - VideoSource(const VideoSource& source); - VideoSource(VideoSource&& other) noexcept; - VideoSource& operator=(VideoSource other) noexcept; - ~VideoSource(); + + VideoSource(const VideoSource& source) + : m_handle( + source.m_handle == 0 ? 0 : CopySource(source.m_handle, &m_status)) { + } + + VideoSource(VideoSource&& other) noexcept : VideoSource() { + swap(*this, other); + } + + VideoSource& operator=(VideoSource other) noexcept { + swap(*this, other); + return *this; + } + + ~VideoSource() { + m_status = 0; + if (m_handle != 0) { + ReleaseSource(m_handle, &m_status); + } + } explicit operator bool() const { return m_handle != 0; } @@ -264,18 +326,27 @@ class VideoSource { /** * Get the kind of the source. */ - Kind GetKind() const; + Kind GetKind() const { + m_status = 0; + return static_cast(GetSourceKind(m_handle, &m_status)); + } /** * Get the name of the source. The name is an arbitrary identifier * provided when the source is created, and should be unique. */ - std::string GetName() const; + std::string GetName() const { + m_status = 0; + return GetSourceName(m_handle, &m_status); + } /** * Get the source description. This is source-kind specific. */ - std::string GetDescription() const; + std::string GetDescription() const { + m_status = 0; + return GetSourceDescription(m_handle, &m_status); + } /** * Get the last time a frame was captured. @@ -283,7 +354,10 @@ class VideoSource { * * @return Time in 1 us increments. */ - uint64_t GetLastFrameTime() const; + uint64_t GetLastFrameTime() const { + m_status = 0; + return GetSourceLastFrameTime(m_handle, &m_status); + } /** * Sets the connection strategy. By default, the source will automatically @@ -294,12 +368,21 @@ class VideoSource { * * @param strategy connection strategy (auto, keep open, or force close) */ - void SetConnectionStrategy(ConnectionStrategy strategy); + void SetConnectionStrategy(ConnectionStrategy strategy) { + m_status = 0; + SetSourceConnectionStrategy( + m_handle, + static_cast(static_cast(strategy)), + &m_status); + } /** * Is the source currently connected to whatever is providing the images? */ - bool IsConnected() const; + bool IsConnected() const { + m_status = 0; + return IsSourceConnected(m_handle, &m_status); + } /** * Gets source enable status. This is determined with a combination of @@ -307,7 +390,10 @@ class VideoSource { * * @return True if enabled, false otherwise. */ - bool IsEnabled() const; + bool IsEnabled() const { + m_status = 0; + return IsSourceEnabled(m_handle, &m_status); + } /** Get a property. * @@ -315,7 +401,10 @@ class VideoSource { * @return Property contents (of kind Property::kNone if no property with * the given name exists) */ - VideoProperty GetProperty(std::string_view name); + VideoProperty GetProperty(std::string_view name) { + m_status = 0; + return VideoProperty{GetSourceProperty(m_handle, name, &m_status)}; + } /** * Enumerate all properties of this source. @@ -325,14 +414,20 @@ class VideoSource { /** * Get the current video mode. */ - VideoMode GetVideoMode() const; + VideoMode GetVideoMode() const { + m_status = 0; + return GetSourceVideoMode(m_handle, &m_status); + } /** * Set the video mode. * * @param mode Video mode */ - bool SetVideoMode(const VideoMode& mode); + bool SetVideoMode(const VideoMode& mode) { + m_status = 0; + return SetSourceVideoMode(m_handle, mode, &m_status); + } /** * Set the video mode. @@ -344,7 +439,11 @@ class VideoSource { * @return True if set successfully */ bool SetVideoMode(VideoMode::PixelFormat pixelFormat, int width, int height, - int fps); + int fps) { + m_status = 0; + return SetSourceVideoMode( + m_handle, VideoMode{pixelFormat, width, height, fps}, &m_status); + } /** * Set the pixel format. @@ -352,7 +451,10 @@ class VideoSource { * @param pixelFormat desired pixel format * @return True if set successfully */ - bool SetPixelFormat(VideoMode::PixelFormat pixelFormat); + bool SetPixelFormat(VideoMode::PixelFormat pixelFormat) { + m_status = 0; + return SetSourcePixelFormat(m_handle, pixelFormat, &m_status); + } /** * Set the resolution. @@ -361,7 +463,10 @@ class VideoSource { * @param height desired height * @return True if set successfully */ - bool SetResolution(int width, int height); + bool SetResolution(int width, int height) { + m_status = 0; + return SetSourceResolution(m_handle, width, height, &m_status); + } /** * Set the frames per second (FPS). @@ -369,7 +474,10 @@ class VideoSource { * @param fps desired FPS * @return True if set successfully */ - bool SetFPS(int fps); + bool SetFPS(int fps) { + m_status = 0; + return SetSourceFPS(m_handle, fps, &m_status); + } /** * Set video mode and properties from a JSON configuration string. @@ -397,7 +505,10 @@ class VideoSource { * @param config configuration * @return True if set successfully */ - bool SetConfigJson(std::string_view config); + bool SetConfigJson(std::string_view config) { + m_status = 0; + return SetSourceConfigJson(m_handle, config, &m_status); + } /** * Set video mode and properties from a JSON configuration object. @@ -405,14 +516,20 @@ class VideoSource { * @param config configuration * @return True if set successfully */ - bool SetConfigJson(const wpi::json& config); + bool SetConfigJson(const wpi::json& config) { + m_status = 0; + return SetSourceConfigJson(m_handle, config, &m_status); + } /** * Get a JSON configuration string. * * @return JSON configuration string */ - std::string GetConfigJson() const; + std::string GetConfigJson() const { + m_status = 0; + return GetSourceConfigJson(m_handle, &m_status); + } /** * Get a JSON configuration object. @@ -428,7 +545,11 @@ class VideoSource { * * @return Actual FPS averaged over the telemetry period. */ - double GetActualFPS() const; + double GetActualFPS() const { + m_status = 0; + return cs::GetTelemetryAverageValue(m_handle, CS_SOURCE_FRAMES_RECEIVED, + &m_status); + } /** * Get the data rate (in bytes per second). @@ -437,12 +558,19 @@ class VideoSource { * * @return Data rate averaged over the telemetry period. */ - double GetActualDataRate() const; + double GetActualDataRate() const { + m_status = 0; + return cs::GetTelemetryAverageValue(m_handle, CS_SOURCE_BYTES_RECEIVED, + &m_status); + } /** * Enumerate all known video modes for this source. */ - std::vector EnumerateVideoModes() const; + std::vector EnumerateVideoModes() const { + CS_Status status = 0; + return EnumerateSourceVideoModes(m_handle, &status); + } CS_Status GetLastStatus() const { return m_status; } @@ -501,42 +629,66 @@ class VideoCamera : public VideoSource { /** * Set the brightness, as a percentage (0-100). */ - void SetBrightness(int brightness); + void SetBrightness(int brightness) { + m_status = 0; + SetCameraBrightness(m_handle, brightness, &m_status); + } /** * Get the brightness, as a percentage (0-100). */ - int GetBrightness(); + int GetBrightness() { + m_status = 0; + return GetCameraBrightness(m_handle, &m_status); + } /** * Set the white balance to auto. */ - void SetWhiteBalanceAuto(); + void SetWhiteBalanceAuto() { + m_status = 0; + SetCameraWhiteBalanceAuto(m_handle, &m_status); + } /** * Set the white balance to hold current. */ - void SetWhiteBalanceHoldCurrent(); + void SetWhiteBalanceHoldCurrent() { + m_status = 0; + SetCameraWhiteBalanceHoldCurrent(m_handle, &m_status); + } /** * Set the white balance to manual, with specified color temperature. */ - void SetWhiteBalanceManual(int value); + void SetWhiteBalanceManual(int value) { + m_status = 0; + SetCameraWhiteBalanceManual(m_handle, value, &m_status); + } /** * Set the exposure to auto aperture. */ - void SetExposureAuto(); + void SetExposureAuto() { + m_status = 0; + SetCameraExposureAuto(m_handle, &m_status); + } /** * Set the exposure to hold current. */ - void SetExposureHoldCurrent(); + void SetExposureHoldCurrent() { + m_status = 0; + SetCameraExposureHoldCurrent(m_handle, &m_status); + } /** * Set the exposure to manual, as a percentage (0-100). */ - void SetExposureManual(int value); + void SetExposureManual(int value) { + m_status = 0; + SetCameraExposureManual(m_handle, value, &m_status); + } protected: explicit VideoCamera(CS_Source handle) : VideoSource(handle) {} @@ -555,7 +707,9 @@ class UsbCamera : public VideoCamera { * @param name Source name (arbitrary unique identifier) * @param dev Device number (e.g. 0 for /dev/video0) */ - UsbCamera(std::string_view name, int dev); + UsbCamera(std::string_view name, int dev) { + m_handle = CreateUsbCameraDev(name, dev, &m_status); + } /** * Create a source for a USB camera based on device path. @@ -563,36 +717,54 @@ class UsbCamera : public VideoCamera { * @param name Source name (arbitrary unique identifier) * @param path Path to device (e.g. "/dev/video0" on Linux) */ - UsbCamera(std::string_view name, std::string_view path); + UsbCamera(std::string_view name, std::string_view path) { + m_handle = CreateUsbCameraPath(name, path, &m_status); + } /** * Enumerate USB cameras on the local system. * * @return Vector of USB camera information (one for each camera) */ - static std::vector EnumerateUsbCameras(); + static std::vector EnumerateUsbCameras() { + CS_Status status = 0; + return ::cs::EnumerateUsbCameras(&status); + } /** * Change the path to the device. */ - void SetPath(std::string_view path); + void SetPath(std::string_view path) { + m_status = 0; + return ::cs::SetUsbCameraPath(m_handle, path, &m_status); + } /** * Get the path to the device. */ - std::string GetPath() const; + std::string GetPath() const { + m_status = 0; + return ::cs::GetUsbCameraPath(m_handle, &m_status); + } /** * Get the full camera information for the device. */ - UsbCameraInfo GetInfo() const; + UsbCameraInfo GetInfo() const { + m_status = 0; + return ::cs::GetUsbCameraInfo(m_handle, &m_status); + } /** * Set how verbose the camera connection messages are. * * @param level 0=don't display Connecting message, 1=do display message */ - void SetConnectVerbose(int level); + void SetConnectVerbose(int level) { + m_status = 0; + SetProperty(GetSourceProperty(m_handle, "connect_verbose", &m_status), + level, &m_status); + } }; /** @@ -622,7 +794,11 @@ class HttpCamera : public VideoCamera { * @param kind Camera kind (e.g. kAxis) */ HttpCamera(std::string_view name, std::string_view url, - HttpCameraKind kind = kUnknown); + HttpCameraKind kind = kUnknown) { + m_handle = CreateHttpCamera( + name, url, static_cast(static_cast(kind)), + &m_status); + } /** * Create a source for a MJPEG-over-HTTP (IP) camera. @@ -632,7 +808,11 @@ class HttpCamera : public VideoCamera { * @param kind Camera kind (e.g. kAxis) */ HttpCamera(std::string_view name, const char* url, - HttpCameraKind kind = kUnknown); + HttpCameraKind kind = kUnknown) { + m_handle = CreateHttpCamera( + name, url, static_cast(static_cast(kind)), + &m_status); + } /** * Create a source for a MJPEG-over-HTTP (IP) camera. @@ -642,7 +822,8 @@ class HttpCamera : public VideoCamera { * @param kind Camera kind (e.g. kAxis) */ HttpCamera(std::string_view name, const std::string& url, - HttpCameraKind kind = kUnknown); + HttpCameraKind kind = kUnknown) + : HttpCamera(name, std::string_view{url}, kind) {} /** * Create a source for a MJPEG-over-HTTP (IP) camera. @@ -652,7 +833,11 @@ class HttpCamera : public VideoCamera { * @param kind Camera kind (e.g. kAxis) */ HttpCamera(std::string_view name, std::span urls, - HttpCameraKind kind = kUnknown); + HttpCameraKind kind = kUnknown) { + m_handle = CreateHttpCamera( + name, urls, static_cast(static_cast(kind)), + &m_status); + } /** * Create a source for a MJPEG-over-HTTP (IP) camera. @@ -663,7 +848,16 @@ class HttpCamera : public VideoCamera { */ template HttpCamera(std::string_view name, std::initializer_list urls, - HttpCameraKind kind = kUnknown); + HttpCameraKind kind = kUnknown) { + std::vector vec; + vec.reserve(urls.size()); + for (const auto& url : urls) { + vec.emplace_back(url); + } + m_handle = CreateHttpCamera( + name, vec, static_cast(static_cast(kind)), + &m_status); + } /** * Get the kind of HTTP camera. @@ -671,23 +865,41 @@ class HttpCamera : public VideoCamera { *

Autodetection can result in returning a different value than the camera * was created with. */ - HttpCameraKind GetHttpCameraKind() const; + HttpCameraKind GetHttpCameraKind() const { + m_status = 0; + return static_cast( + static_cast(::cs::GetHttpCameraKind(m_handle, &m_status))); + } /** * Change the URLs used to connect to the camera. */ - void SetUrls(std::span urls); + void SetUrls(std::span urls) { + m_status = 0; + ::cs::SetHttpCameraUrls(m_handle, urls, &m_status); + } /** * Change the URLs used to connect to the camera. */ template - void SetUrls(std::initializer_list urls); + void SetUrls(std::initializer_list urls) { + std::vector vec; + vec.reserve(urls.size()); + for (const auto& url : urls) { + vec.emplace_back(url); + } + m_status = 0; + ::cs::SetHttpCameraUrls(m_handle, vec, &m_status); + } /** * Get the URLs used to connect to the camera. */ - std::vector GetUrls() const; + std::vector GetUrls() const { + m_status = 0; + return ::cs::GetHttpCameraUrls(m_handle, &m_status); + } }; /** @@ -697,9 +909,26 @@ class HttpCamera : public VideoCamera { */ class [[deprecated("Use HttpCamera instead.")]] AxisCamera : public HttpCamera { static std::string HostToUrl(std::string_view host); - static std::vector HostToUrl(std::span hosts); + + static std::vector HostToUrl( + std::span hosts) { + std::vector rv; + rv.reserve(hosts.size()); + for (const auto& host : hosts) { + rv.emplace_back(HostToUrl(std::string_view{host})); + } + return rv; + } + template - static std::vector HostToUrl(std::initializer_list hosts); + static std::vector HostToUrl(std::initializer_list hosts) { + std::vector rv; + rv.reserve(hosts.size()); + for (const auto& host : hosts) { + rv.emplace_back(HostToUrl(std::string_view{host})); + } + return rv; + } public: /** @@ -708,7 +937,8 @@ class [[deprecated("Use HttpCamera instead.")]] AxisCamera : public HttpCamera { * @param name Source name (arbitrary unique identifier) * @param host Camera host IP or DNS name (e.g. "10.x.y.11") */ - AxisCamera(std::string_view name, std::string_view host); + AxisCamera(std::string_view name, std::string_view host) + : HttpCamera(name, HostToUrl(host), kAxis) {} /** * Create a source for an Axis IP camera. @@ -716,7 +946,8 @@ class [[deprecated("Use HttpCamera instead.")]] AxisCamera : public HttpCamera { * @param name Source name (arbitrary unique identifier) * @param host Camera host IP or DNS name (e.g. "10.x.y.11") */ - AxisCamera(std::string_view name, const char* host); + AxisCamera(std::string_view name, const char* host) + : HttpCamera(name, HostToUrl(host), kAxis) {} /** * Create a source for an Axis IP camera. @@ -724,7 +955,8 @@ class [[deprecated("Use HttpCamera instead.")]] AxisCamera : public HttpCamera { * @param name Source name (arbitrary unique identifier) * @param host Camera host IP or DNS name (e.g. "10.x.y.11") */ - AxisCamera(std::string_view name, const std::string& host); + AxisCamera(std::string_view name, const std::string& host) + : HttpCamera(name, HostToUrl(std::string_view{host}), kAxis) {} /** * Create a source for an Axis IP camera. @@ -732,7 +964,8 @@ class [[deprecated("Use HttpCamera instead.")]] AxisCamera : public HttpCamera { * @param name Source name (arbitrary unique identifier) * @param hosts Array of Camera host IPs/DNS names */ - AxisCamera(std::string_view name, std::span hosts); + AxisCamera(std::string_view name, std::span hosts) + : HttpCamera(name, HostToUrl(hosts), kAxis) {} /** * Create a source for an Axis IP camera. @@ -741,7 +974,8 @@ class [[deprecated("Use HttpCamera instead.")]] AxisCamera : public HttpCamera { * @param hosts Array of Camera host IPs/DNS names */ template - AxisCamera(std::string_view name, std::initializer_list hosts); + AxisCamera(std::string_view name, std::initializer_list hosts) + : HttpCamera(name, HostToUrl(hosts), kAxis) {} }; /** @@ -758,21 +992,30 @@ class ImageSource : public VideoSource { * * @param msg Notification message. */ - void NotifyError(std::string_view msg); + void NotifyError(std::string_view msg) { + m_status = 0; + NotifySourceError(m_handle, msg, &m_status); + } /** * Set source connection status. Defaults to true. * * @param connected True for connected, false for disconnected */ - void SetConnected(bool connected); + void SetConnected(bool connected) { + m_status = 0; + SetSourceConnected(m_handle, connected, &m_status); + } /** * Set source description. * * @param description Description */ - void SetDescription(std::string_view description); + void SetDescription(std::string_view description) { + m_status = 0; + SetSourceDescription(m_handle, description, &m_status); + } /** * Create a property. @@ -788,7 +1031,12 @@ class ImageSource : public VideoSource { */ VideoProperty CreateProperty(std::string_view name, VideoProperty::Kind kind, int minimum, int maximum, int step, - int defaultValue, int value); + int defaultValue, int value) { + m_status = 0; + return VideoProperty{CreateSourceProperty( + m_handle, name, static_cast(static_cast(kind)), + minimum, maximum, step, defaultValue, value, &m_status)}; + } /** * Create an integer property. @@ -803,7 +1051,14 @@ class ImageSource : public VideoSource { */ VideoProperty CreateIntegerProperty(std::string_view name, int minimum, int maximum, int step, int defaultValue, - int value); + int value) { + m_status = 0; + return VideoProperty{CreateSourceProperty( + m_handle, name, + static_cast( + static_cast(VideoProperty::Kind::kInteger)), + minimum, maximum, step, defaultValue, value, &m_status)}; + } /** * Create a boolean property. @@ -814,7 +1069,14 @@ class ImageSource : public VideoSource { * @return Property */ VideoProperty CreateBooleanProperty(std::string_view name, bool defaultValue, - bool value); + bool value) { + m_status = 0; + return VideoProperty{CreateSourceProperty( + m_handle, name, + static_cast( + static_cast(VideoProperty::Kind::kBoolean)), + 0, 1, 1, defaultValue ? 1 : 0, value ? 1 : 0, &m_status)}; + } /** * Create a string property. @@ -824,7 +1086,16 @@ class ImageSource : public VideoSource { * @return Property */ VideoProperty CreateStringProperty(std::string_view name, - std::string_view value); + std::string_view value) { + m_status = 0; + auto prop = VideoProperty{CreateSourceProperty( + m_handle, name, + static_cast( + static_cast(VideoProperty::Kind::kString)), + 0, 0, 0, 0, 0, &m_status)}; + prop.SetString(value); + return prop; + } /** * Configure enum property choices. @@ -833,7 +1104,11 @@ class ImageSource : public VideoSource { * @param choices Choices */ void SetEnumPropertyChoices(const VideoProperty& property, - std::span choices); + std::span choices) { + m_status = 0; + SetSourceEnumPropertyChoices(m_handle, property.m_handle, choices, + &m_status); + } /** * Configure enum property choices. @@ -843,7 +1118,15 @@ class ImageSource : public VideoSource { */ template void SetEnumPropertyChoices(const VideoProperty& property, - std::initializer_list choices); + std::initializer_list choices) { + std::vector 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); + } }; /** @@ -866,10 +1149,23 @@ class VideoSink { }; VideoSink() noexcept = default; - VideoSink(const VideoSink& sink); - VideoSink(VideoSink&& sink) noexcept; - VideoSink& operator=(VideoSink other) noexcept; - ~VideoSink(); + + VideoSink(const VideoSink& sink) + : m_handle(sink.m_handle == 0 ? 0 : CopySink(sink.m_handle, &m_status)) {} + + VideoSink(VideoSink&& other) noexcept : VideoSink() { swap(*this, other); } + + VideoSink& operator=(VideoSink other) noexcept { + swap(*this, other); + return *this; + } + + ~VideoSink() { + m_status = 0; + if (m_handle != 0) { + ReleaseSink(m_handle, &m_status); + } + } /** * Returns true if the VideoSink is valid. @@ -892,18 +1188,27 @@ class VideoSink { /** * Get the kind of the sink. */ - Kind GetKind() const; + Kind GetKind() const { + m_status = 0; + return static_cast(GetSinkKind(m_handle, &m_status)); + } /** * Get the name of the sink. The name is an arbitrary identifier * provided when the sink is created, and should be unique. */ - std::string GetName() const; + std::string GetName() const { + m_status = 0; + return GetSinkName(m_handle, &m_status); + } /** * Get the sink description. This is sink-kind specific. */ - std::string GetDescription() const; + std::string GetDescription() const { + m_status = 0; + return GetSinkDescription(m_handle, &m_status); + } /** * Get a property of the sink. @@ -912,7 +1217,10 @@ class VideoSink { * @return Property (kind Property::kNone if no property with * the given name exists) */ - VideoProperty GetProperty(std::string_view name); + VideoProperty GetProperty(std::string_view name) { + m_status = 0; + return VideoProperty{GetSinkProperty(m_handle, name, &m_status)}; + } /** * Enumerate all properties of this sink. @@ -938,7 +1246,10 @@ class VideoSink { * @param config configuration * @return True if set successfully */ - bool SetConfigJson(std::string_view config); + bool SetConfigJson(std::string_view config) { + m_status = 0; + return SetSinkConfigJson(m_handle, config, &m_status); + } /** * Set properties from a JSON configuration object. @@ -946,14 +1257,20 @@ class VideoSink { * @param config configuration * @return True if set successfully */ - bool SetConfigJson(const wpi::json& config); + bool SetConfigJson(const wpi::json& config) { + m_status = 0; + return SetSinkConfigJson(m_handle, config, &m_status); + } /** * Get a JSON configuration string. * * @return JSON configuration string */ - std::string GetConfigJson() const; + std::string GetConfigJson() const { + m_status = 0; + return GetSinkConfigJson(m_handle, &m_status); + } /** * Get a JSON configuration object. @@ -969,14 +1286,25 @@ class VideoSink { * * @param source Source */ - void SetSource(VideoSource source); + void SetSource(VideoSource source) { + m_status = 0; + if (!source) { + SetSinkSource(m_handle, 0, &m_status); + } else { + SetSinkSource(m_handle, source.m_handle, &m_status); + } + } /** * Get the connected source. * * @return Connected source (empty if none connected). */ - VideoSource GetSource() const; + VideoSource GetSource() const { + m_status = 0; + auto handle = GetSinkSource(m_handle, &m_status); + return VideoSource{handle == 0 ? 0 : CopySource(handle, &m_status)}; + } /** * Get a property of the associated source. @@ -985,7 +1313,10 @@ class VideoSink { * @return Property (kind Property::kNone if no property with * the given name exists or no source connected) */ - VideoProperty GetSourceProperty(std::string_view name); + VideoProperty GetSourceProperty(std::string_view name) { + m_status = 0; + return VideoProperty{GetSinkSourceProperty(m_handle, name, &m_status)}; + } CS_Status GetLastStatus() const { return m_status; } @@ -1023,7 +1354,9 @@ class MjpegServer : public VideoSink { * @param listenAddress TCP listen address (empty string for all addresses) * @param port TCP port number */ - MjpegServer(std::string_view name, std::string_view listenAddress, int port); + MjpegServer(std::string_view name, std::string_view listenAddress, int port) { + m_handle = CreateMjpegServer(name, listenAddress, port, &m_status); + } /** * Create a MJPEG-over-HTTP server sink. @@ -1036,12 +1369,18 @@ class MjpegServer : public VideoSink { /** * Get the listen address of the server. */ - std::string GetListenAddress() const; + std::string GetListenAddress() const { + m_status = 0; + return cs::GetMjpegServerListenAddress(m_handle, &m_status); + } /** * Get the port number of the server. */ - int GetPort() const; + int GetPort() const { + m_status = 0; + return cs::GetMjpegServerPort(m_handle, &m_status); + } /** * Set the stream resolution for clients that don't specify it. @@ -1057,7 +1396,13 @@ class MjpegServer : public VideoSink { * @param width width, 0 for unspecified * @param height height, 0 for unspecified */ - void SetResolution(int width, int height); + void 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); + } /** * Set the stream frames per second (FPS) for clients that don't specify it. @@ -1066,7 +1411,10 @@ class MjpegServer : public VideoSink { * * @param fps FPS, 0 for unspecified */ - void SetFPS(int fps); + void SetFPS(int fps) { + m_status = 0; + SetProperty(GetSinkProperty(m_handle, "fps", &m_status), fps, &m_status); + } /** * Set the compression for clients that don't specify it. @@ -1077,7 +1425,11 @@ class MjpegServer : public VideoSink { * * @param quality JPEG compression quality (0-100), -1 for unspecified */ - void SetCompression(int quality); + void SetCompression(int quality) { + m_status = 0; + SetProperty(GetSinkProperty(m_handle, "compression", &m_status), quality, + &m_status); + } /** * Set the default compression used for non-MJPEG sources. If not set, @@ -1086,7 +1438,11 @@ class MjpegServer : public VideoSink { * * @param quality JPEG compression quality (0-100) */ - void SetDefaultCompression(int quality); + void SetDefaultCompression(int quality) { + m_status = 0; + SetProperty(GetSinkProperty(m_handle, "default_compression", &m_status), + quality, &m_status); + } }; /** @@ -1102,13 +1458,19 @@ class ImageSink : public VideoSink { * * @param description Description */ - void SetDescription(std::string_view description); + void SetDescription(std::string_view description) { + m_status = 0; + SetSinkDescription(m_handle, description, &m_status); + } /** * Get error string. Call this if WaitForFrame() returns 0 to determine * what the error is. */ - std::string GetError() const; + std::string GetError() const { + m_status = 0; + return GetSinkError(m_handle, &m_status); + } /** * Enable or disable getting new frames. @@ -1117,7 +1479,10 @@ class ImageSink : public VideoSink { * be called and WaitForFrame() to not return. This can be used to save * processor resources when frames are not needed. */ - void SetEnabled(bool enabled); + void SetEnabled(bool enabled) { + m_status = 0; + SetSinkEnabled(m_handle, enabled, &m_status); + } }; /** @@ -1130,21 +1495,31 @@ class VideoEvent : public RawEvent { * * @return The source associated with the event (if any). */ - VideoSource GetSource() const; + VideoSource GetSource() const { + CS_Status status = 0; + return VideoSource{sourceHandle == 0 ? 0 + : CopySource(sourceHandle, &status)}; + } /** * Returns the sink associated with the event (if any). * * @return The sink associated with the event (if any). */ - VideoSink GetSink() const; + VideoSink GetSink() const { + CS_Status status = 0; + return VideoSink{sinkHandle == 0 ? 0 : CopySink(sinkHandle, &status)}; + } /** * Returns the property associated with the event (if any). * * @return The property associated with the event (if any). */ - VideoProperty GetProperty() const; + VideoProperty GetProperty() const { + return VideoProperty{propertyHandle, + static_cast(propertyKind)}; + } }; /** @@ -1164,13 +1539,33 @@ class VideoListener { * a representative set of events for the current library state. */ VideoListener(std::function callback, - int eventMask, bool immediateNotify); + int eventMask, bool immediateNotify) { + CS_Status status = 0; + m_handle = AddListener( + [=](const RawEvent& event) { + callback(static_cast(event)); + }, + eventMask, immediateNotify, &status); + } VideoListener(const VideoListener&) = delete; VideoListener& operator=(const VideoListener&) = delete; - VideoListener(VideoListener&& other) noexcept; - VideoListener& operator=(VideoListener&& other) noexcept; - ~VideoListener(); + + VideoListener(VideoListener&& other) noexcept : VideoListener() { + swap(*this, other); + } + + VideoListener& operator=(VideoListener&& other) noexcept { + swap(*this, other); + return *this; + } + + ~VideoListener() { + CS_Status status = 0; + if (m_handle != 0) { + RemoveListener(m_handle, &status); + } + } friend void swap(VideoListener& first, VideoListener& second) noexcept { using std::swap; @@ -1185,6 +1580,4 @@ class VideoListener { } // namespace cs -#include "cscore_oo.inc" - #endif // CSCORE_CSCORE_OO_H_ diff --git a/cscore/src/main/native/include/cscore_oo.inc b/cscore/src/main/native/include/cscore_oo.inc deleted file mode 100644 index 20960f20e65..00000000000 --- a/cscore/src/main/native/include/cscore_oo.inc +++ /dev/null @@ -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 -#include -#include -#include -#include - -#include - -#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& 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 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(static_cast(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(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(static_cast(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 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 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(static_cast(kind)), - &m_status); -} - -inline HttpCamera::HttpCamera(std::string_view name, const char* url, - HttpCameraKind kind) { - m_handle = CreateHttpCamera( - name, url, static_cast(static_cast(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 urls, - HttpCameraKind kind) { - m_handle = CreateHttpCamera( - name, urls, static_cast(static_cast(kind)), - &m_status); -} - -template -inline HttpCamera::HttpCamera(std::string_view name, - std::initializer_list urls, - HttpCameraKind kind) { - std::vector vec; - vec.reserve(urls.size()); - for (const auto& url : urls) { - vec.emplace_back(url); - } - m_handle = CreateHttpCamera( - name, vec, static_cast(static_cast(kind)), - &m_status); -} - -inline HttpCamera::HttpCameraKind HttpCamera::GetHttpCameraKind() const { - m_status = 0; - return static_cast( - static_cast(::cs::GetHttpCameraKind(m_handle, &m_status))); -} - -inline void HttpCamera::SetUrls(std::span urls) { - m_status = 0; - ::cs::SetHttpCameraUrls(m_handle, urls, &m_status); -} - -template -inline void HttpCamera::SetUrls(std::initializer_list urls) { - std::vector 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 HttpCamera::GetUrls() const { - m_status = 0; - return ::cs::GetHttpCameraUrls(m_handle, &m_status); -} -WPI_IGNORE_DEPRECATED -inline std::vector AxisCamera::HostToUrl( - std::span hosts) { - std::vector rv; - rv.reserve(hosts.size()); - for (const auto& host : hosts) { - rv.emplace_back(HostToUrl(std::string_view{host})); - } - return rv; -} - -template -inline std::vector AxisCamera::HostToUrl( - std::initializer_list hosts) { - std::vector 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 hosts) - : HttpCamera(name, HostToUrl(hosts), kAxis) {} - -template -inline AxisCamera::AxisCamera(std::string_view name, - std::initializer_list 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(static_cast(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( - static_cast(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( - static_cast(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( - static_cast(VideoProperty::Kind::kString)), - 0, 0, 0, 0, 0, &m_status)}; - prop.SetString(value); - return prop; -} - -inline void ImageSource::SetEnumPropertyChoices( - const VideoProperty& property, std::span choices) { - m_status = 0; - SetSourceEnumPropertyChoices(m_handle, property.m_handle, choices, &m_status); -} - -template -inline void ImageSource::SetEnumPropertyChoices( - const VideoProperty& property, std::initializer_list choices) { - std::vector 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(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(propertyKind)}; -} - -inline VideoListener::VideoListener( - std::function callback, int eventMask, - bool immediateNotify) { - CS_Status status = 0; - m_handle = AddListener( - [=](const RawEvent& event) { - callback(static_cast(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_ diff --git a/glass/src/lib/native/cpp/other/Field2D.cpp b/glass/src/lib/native/cpp/other/Field2D.cpp index 505a9d60550..10019c620e5 100644 --- a/glass/src/lib/native/cpp/other/Field2D.cpp +++ b/glass/src/lib/native/cpp/other/Field2D.cpp @@ -591,6 +591,12 @@ FieldFrameData FieldInfo::GetFrameData(ImVec2 min, ImVec2 max) const { max.x -= 20; min.y += 20; max.y -= 20; + + // also pad the image so it's the same size as the box + ffd.imageMin.x += 20; + ffd.imageMax.x -= 20; + ffd.imageMin.y += 20; + ffd.imageMax.y -= 20; } ffd.min = min; diff --git a/glass/src/lib/native/include/glass/Provider.h b/glass/src/lib/native/include/glass/Provider.h index f620d523b8d..95750de486e 100644 --- a/glass/src/lib/native/include/glass/Provider.h +++ b/glass/src/lib/native/include/glass/Provider.h @@ -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>; 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 MakeModelEntry( std::string_view name, ExistsFunc exists, CreateModelFunc createModel) { @@ -166,5 +223,3 @@ class Provider : public WindowManager { }; } // namespace glass - -#include "Provider.inc" diff --git a/glass/src/lib/native/include/glass/Provider.inc b/glass/src/lib/native/include/glass/Provider.inc deleted file mode 100644 index 7370cca13b1..00000000000 --- a/glass/src/lib/native/include/glass/Provider.inc +++ /dev/null @@ -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 - -#include "glass/Provider.h" - -namespace glass { - -template -void Provider::GlobalInit() { - WindowManager::GlobalInit(); - wpi::gui::AddEarlyExecute([this] { Update(); }); -} - -template -void Provider::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 -void Provider::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 -void Provider::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 -void Provider::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 -void Provider::Update() { - // update entries - for (auto&& entry : m_modelEntries) { - if (entry->model) { - entry->model->Update(); - } - } -} - -template -typename Provider::ModelEntries::iterator -Provider::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 Provider::ViewEntries::iterator -Provider::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 diff --git a/ntcore/src/generate/main/native/include/networktables/Topic.h.jinja b/ntcore/src/generate/main/native/include/networktables/Topic.h.jinja index 93abc498713..19939c0b946 100644 --- a/ntcore/src/generate/main/native/include/networktables/Topic.h.jinja +++ b/ntcore/src/generate/main/native/include/networktables/Topic.h.jinja @@ -15,7 +15,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -50,7 +52,9 @@ class {{ TypeName }}Subscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - {{ TypeName }}Subscriber(NT_Subscriber handle, ParamType defaultValue); + {{ TypeName }}Subscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{{ '{' }}{{ cpp.DefaultValueCopy|default('defaultValue') }}} {} /** * Get the last published value. @@ -58,7 +62,9 @@ class {{ TypeName }}Subscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -67,7 +73,9 @@ class {{ TypeName }}Subscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::Get{{ TypeName }}(m_subHandle, defaultValue); + } {% if cpp.SmallRetType and cpp.SmallElemType %} /** * Get the last published value. @@ -76,7 +84,9 @@ class {{ TypeName }}Subscriber : public Subscriber { * @param buf storage for returned value * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf) const; + SmallRetType Get(wpi::SmallVectorImpl& buf) const { + return Get(buf, m_defaultValue); + } /** * Get the last published value. @@ -86,7 +96,9 @@ class {{ TypeName }}Subscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const; + SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { + return nt::Get{{ TypeName }}(m_subHandle, buf, defaultValue); + } {% endif %} /** * Get the last published value along with its timestamp @@ -95,7 +107,9 @@ class {{ TypeName }}Subscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -105,7 +119,9 @@ class {{ TypeName }}Subscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomic{{ TypeName }}(m_subHandle, defaultValue); + } {% if cpp.SmallRetType and cpp.SmallElemType %} /** * Get the last published value along with its timestamp. @@ -116,7 +132,9 @@ class {{ TypeName }}Subscriber : public Subscriber { * @return timestamped value */ TimestampedValueViewType GetAtomic( - wpi::SmallVectorImpl& buf) const; + wpi::SmallVectorImpl& buf) const { + return GetAtomic(buf, m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -129,7 +147,9 @@ class {{ TypeName }}Subscriber : public Subscriber { */ TimestampedValueViewType GetAtomic( wpi::SmallVectorImpl& buf, - ParamType defaultValue) const; + ParamType defaultValue) const { + return nt::GetAtomic{{ TypeName }}(m_subHandle, buf, defaultValue); + } {% endif %} /** * Get an array of all value changes since the last call to ReadQueue. @@ -141,7 +161,9 @@ class {{ TypeName }}Subscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueue{{ TypeName }}(m_subHandle); + } /** * Get the corresponding topic. @@ -176,7 +198,7 @@ class {{ TypeName }}Publisher : public Publisher { * * @param handle Native handle */ - explicit {{ TypeName }}Publisher(NT_Publisher handle); + explicit {{ TypeName }}Publisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -184,7 +206,9 @@ class {{ TypeName }}Publisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::Set{{ TypeName }}(m_pubHandle, value, time); + } /** * Publish a default value. @@ -193,7 +217,9 @@ class {{ TypeName }}Publisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefault{{ TypeName }}(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -231,7 +257,9 @@ class {{ TypeName }}Entry final : public {{ TypeName }}Subscriber, * @param handle Native handle * @param defaultValue Default value */ - {{ TypeName }}Entry(NT_Entry handle, ParamType defaultValue); + {{ TypeName }}Entry(NT_Entry handle, ParamType defaultValue) + : {{ TypeName }}Subscriber{handle, defaultValue}, + {{ TypeName }}Publisher{handle} {} /** * Determines if the native handle is valid. @@ -257,7 +285,9 @@ class {{ TypeName }}Entry final : public {{ TypeName }}Subscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -314,7 +344,11 @@ class {{ TypeName }}Topic final : public Topic { [[nodiscard]] SubscriberType Subscribe( {% if not TypeString %}std::string_view typeString, {% endif %}ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return {{ TypeName }}Subscriber{ + ::nt::Subscribe(m_handle, NT_{{ cpp.TYPE_NAME }}, {{ TypeString|default('typeString') }}, options), + defaultValue}; + } {%- if TypeString %} /** * Create a new subscriber to the topic, with specific type string. @@ -335,7 +369,11 @@ class {{ TypeName }}Topic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return {{ TypeName }}Subscriber{ + ::nt::Subscribe(m_handle, NT_{{ cpp.TYPE_NAME }}, typeString, options), + defaultValue}; + } {% endif %} /** * Create a new publisher to the topic. @@ -356,7 +394,10 @@ class {{ TypeName }}Topic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish({% if not TypeString %}std::string_view typeString, {% endif %}const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish({% if not TypeString %}std::string_view typeString, {% endif %}const PubSubOptions& options = kDefaultPubSubOptions) { + return {{ TypeName }}Publisher{ + ::nt::Publish(m_handle, NT_{{ cpp.TYPE_NAME }}, {{ TypeString|default('typeString') }}, options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -378,7 +419,10 @@ class {{ TypeName }}Topic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return {{ TypeName }}Publisher{ + ::nt::PublishEx(m_handle, NT_{{ cpp.TYPE_NAME }}, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -405,7 +449,11 @@ class {{ TypeName }}Topic final : public Topic { */ [[nodiscard]] EntryType GetEntry({% if not TypeString %}std::string_view typeString, {% endif %}ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return {{ TypeName }}Entry{ + ::nt::GetEntry(m_handle, NT_{{ cpp.TYPE_NAME }}, {{ TypeString|default('typeString') }}, options), + defaultValue}; + } {%- if TypeString %} /** * Create a new entry for the topic, with specific type string. @@ -430,11 +478,25 @@ class {{ TypeName }}Topic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return {{ TypeName }}Entry{ + ::nt::GetEntry(m_handle, NT_{{ cpp.TYPE_NAME }}, typeString, options), + defaultValue}; + } {% endif %} }; -} // namespace nt +inline {{ TypeName }}Topic {{ TypeName }}Subscriber::GetTopic() const { + return {{ TypeName }}Topic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline {{ TypeName }}Topic {{ TypeName }}Publisher::GetTopic() const { + return {{ TypeName }}Topic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/{{ TypeName }}Topic.inc" +inline {{ TypeName }}Topic {{ TypeName }}Entry::GetTopic() const { + return {{ TypeName }}Topic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generate/main/native/include/networktables/Topic.inc.jinja b/ntcore/src/generate/main/native/include/networktables/Topic.inc.jinja deleted file mode 100644 index 7a5bc7693bf..00000000000 --- a/ntcore/src/generate/main/native/include/networktables/Topic.inc.jinja +++ /dev/null @@ -1,140 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/{{ TypeName }}Topic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline {{ TypeName }}Subscriber::{{ TypeName }}Subscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{{ '{' }}{{ cpp.DefaultValueCopy|default('defaultValue') }}} {} - -inline {{ cpp.ValueType }} {{ TypeName }}Subscriber::Get() const { - return Get(m_defaultValue); -} - -inline {{ cpp.ValueType }} {{ TypeName }}Subscriber::Get( - ParamType defaultValue) const { - return ::nt::Get{{ TypeName }}(m_subHandle, defaultValue); -} -{% if cpp.SmallRetType and cpp.SmallElemType %} -inline {{ cpp.SmallRetType }} {{ TypeName }}Subscriber::Get(wpi::SmallVectorImpl<{{ cpp.SmallElemType }}>& buf) const { - return Get(buf, m_defaultValue); -} - -inline {{ cpp.SmallRetType }} {{ TypeName }}Subscriber::Get(wpi::SmallVectorImpl<{{ cpp.SmallElemType }}>& buf, ParamType defaultValue) const { - return nt::Get{{ TypeName }}(m_subHandle, buf, defaultValue); -} -{% endif %} -inline Timestamped{{ TypeName }} {{ TypeName }}Subscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline Timestamped{{ TypeName }} {{ TypeName }}Subscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomic{{ TypeName }}(m_subHandle, defaultValue); -} -{% if cpp.SmallRetType and cpp.SmallElemType %} -inline Timestamped{{ TypeName }}View {{ TypeName }}Subscriber::GetAtomic(wpi::SmallVectorImpl<{{ cpp.SmallElemType }}>& buf) const { - return GetAtomic(buf, m_defaultValue); -} - -inline Timestamped{{ TypeName }}View {{ TypeName }}Subscriber::GetAtomic(wpi::SmallVectorImpl<{{ cpp.SmallElemType }}>& buf, ParamType defaultValue) const { - return nt::GetAtomic{{ TypeName }}(m_subHandle, buf, defaultValue); -} -{% endif %} -inline std::vector -{{ TypeName }}Subscriber::ReadQueue() { - return ::nt::ReadQueue{{ TypeName }}(m_subHandle); -} - -inline {{ TypeName }}Topic {{ TypeName }}Subscriber::GetTopic() const { - return {{ TypeName }}Topic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline {{ TypeName }}Publisher::{{ TypeName }}Publisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void {{ TypeName }}Publisher::Set(ParamType value, - int64_t time) { - ::nt::Set{{ TypeName }}(m_pubHandle, value, time); -} - -inline void {{ TypeName }}Publisher::SetDefault(ParamType value) { - ::nt::SetDefault{{ TypeName }}(m_pubHandle, value); -} - -inline {{ TypeName }}Topic {{ TypeName }}Publisher::GetTopic() const { - return {{ TypeName }}Topic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline {{ TypeName }}Entry::{{ TypeName }}Entry( - NT_Entry handle, ParamType defaultValue) - : {{ TypeName }}Subscriber{handle, defaultValue}, - {{ TypeName }}Publisher{handle} {} - -inline {{ TypeName }}Topic {{ TypeName }}Entry::GetTopic() const { - return {{ TypeName }}Topic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void {{ TypeName }}Entry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline {{ TypeName }}Subscriber {{ TypeName }}Topic::Subscribe( - {% if not TypeString %}std::string_view typeString, {% endif %}{{ cpp.ParamType }} defaultValue, - const PubSubOptions& options) { - return {{ TypeName }}Subscriber{ - ::nt::Subscribe(m_handle, NT_{{ cpp.TYPE_NAME }}, {{ TypeString|default('typeString') }}, options), - defaultValue}; -} -{%- if TypeString %} -inline {{ TypeName }}Subscriber {{ TypeName }}Topic::SubscribeEx( - std::string_view typeString, {{ cpp.ParamType }} defaultValue, - const PubSubOptions& options) { - return {{ TypeName }}Subscriber{ - ::nt::Subscribe(m_handle, NT_{{ cpp.TYPE_NAME }}, typeString, options), - defaultValue}; -} -{% endif %} -inline {{ TypeName }}Publisher {{ TypeName }}Topic::Publish( - {% if not TypeString %}std::string_view typeString, {% endif %}const PubSubOptions& options) { - return {{ TypeName }}Publisher{ - ::nt::Publish(m_handle, NT_{{ cpp.TYPE_NAME }}, {{ TypeString|default('typeString') }}, options)}; -} - -inline {{ TypeName }}Publisher {{ TypeName }}Topic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return {{ TypeName }}Publisher{ - ::nt::PublishEx(m_handle, NT_{{ cpp.TYPE_NAME }}, typeString, properties, options)}; -} - -inline {{ TypeName }}Entry {{ TypeName }}Topic::GetEntry( - {% if not TypeString %}std::string_view typeString, {% endif %}{{ cpp.ParamType }} defaultValue, - const PubSubOptions& options) { - return {{ TypeName }}Entry{ - ::nt::GetEntry(m_handle, NT_{{ cpp.TYPE_NAME }}, {{ TypeString|default('typeString') }}, options), - defaultValue}; -} -{%- if TypeString %} -inline {{ TypeName }}Entry {{ TypeName }}Topic::GetEntryEx( - std::string_view typeString, {{ cpp.ParamType }} defaultValue, - const PubSubOptions& options) { - return {{ TypeName }}Entry{ - ::nt::GetEntry(m_handle, NT_{{ cpp.TYPE_NAME }}, typeString, options), - defaultValue}; -} -{% endif %} -} // namespace nt - diff --git a/ntcore/src/generated/main/native/include/networktables/BooleanArrayTopic.h b/ntcore/src/generated/main/native/include/networktables/BooleanArrayTopic.h index de89f4b2b08..137c922c279 100644 --- a/ntcore/src/generated/main/native/include/networktables/BooleanArrayTopic.h +++ b/ntcore/src/generated/main/native/include/networktables/BooleanArrayTopic.h @@ -15,7 +15,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -50,7 +52,9 @@ class BooleanArraySubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - BooleanArraySubscriber(NT_Subscriber handle, ParamType defaultValue); + BooleanArraySubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{defaultValue.begin(), defaultValue.end()} {} /** * Get the last published value. @@ -58,7 +62,9 @@ class BooleanArraySubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -67,7 +73,9 @@ class BooleanArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::GetBooleanArray(m_subHandle, defaultValue); + } /** * Get the last published value. @@ -76,7 +84,9 @@ class BooleanArraySubscriber : public Subscriber { * @param buf storage for returned value * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf) const; + SmallRetType Get(wpi::SmallVectorImpl& buf) const { + return Get(buf, m_defaultValue); + } /** * Get the last published value. @@ -86,7 +96,9 @@ class BooleanArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const; + SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { + return nt::GetBooleanArray(m_subHandle, buf, defaultValue); + } /** * Get the last published value along with its timestamp @@ -95,7 +107,9 @@ class BooleanArraySubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -105,7 +119,9 @@ class BooleanArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomicBooleanArray(m_subHandle, defaultValue); + } /** * Get the last published value along with its timestamp. @@ -116,7 +132,9 @@ class BooleanArraySubscriber : public Subscriber { * @return timestamped value */ TimestampedValueViewType GetAtomic( - wpi::SmallVectorImpl& buf) const; + wpi::SmallVectorImpl& buf) const { + return GetAtomic(buf, m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -129,7 +147,9 @@ class BooleanArraySubscriber : public Subscriber { */ TimestampedValueViewType GetAtomic( wpi::SmallVectorImpl& buf, - ParamType defaultValue) const; + ParamType defaultValue) const { + return nt::GetAtomicBooleanArray(m_subHandle, buf, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -141,7 +161,9 @@ class BooleanArraySubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueBooleanArray(m_subHandle); + } /** * Get the corresponding topic. @@ -176,7 +198,7 @@ class BooleanArrayPublisher : public Publisher { * * @param handle Native handle */ - explicit BooleanArrayPublisher(NT_Publisher handle); + explicit BooleanArrayPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -184,7 +206,9 @@ class BooleanArrayPublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetBooleanArray(m_pubHandle, value, time); + } /** * Publish a default value. @@ -193,7 +217,9 @@ class BooleanArrayPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultBooleanArray(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -231,7 +257,9 @@ class BooleanArrayEntry final : public BooleanArraySubscriber, * @param handle Native handle * @param defaultValue Default value */ - BooleanArrayEntry(NT_Entry handle, ParamType defaultValue); + BooleanArrayEntry(NT_Entry handle, ParamType defaultValue) + : BooleanArraySubscriber{handle, defaultValue}, + BooleanArrayPublisher{handle} {} /** * Determines if the native handle is valid. @@ -257,7 +285,9 @@ class BooleanArrayEntry final : public BooleanArraySubscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -309,7 +339,11 @@ class BooleanArrayTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanArraySubscriber{ + ::nt::Subscribe(m_handle, NT_BOOLEAN_ARRAY, "boolean[]", options), + defaultValue}; + } /** * Create a new subscriber to the topic, with specific type string. * @@ -329,7 +363,11 @@ class BooleanArrayTopic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanArraySubscriber{ + ::nt::Subscribe(m_handle, NT_BOOLEAN_ARRAY, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. @@ -347,7 +385,10 @@ class BooleanArrayTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanArrayPublisher{ + ::nt::Publish(m_handle, NT_BOOLEAN_ARRAY, "boolean[]", options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -369,7 +410,10 @@ class BooleanArrayTopic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanArrayPublisher{ + ::nt::PublishEx(m_handle, NT_BOOLEAN_ARRAY, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -393,7 +437,11 @@ class BooleanArrayTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanArrayEntry{ + ::nt::GetEntry(m_handle, NT_BOOLEAN_ARRAY, "boolean[]", options), + defaultValue}; + } /** * Create a new entry for the topic, with specific type string. * @@ -417,10 +465,24 @@ class BooleanArrayTopic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanArrayEntry{ + ::nt::GetEntry(m_handle, NT_BOOLEAN_ARRAY, typeString, options), + defaultValue}; + } }; -} // namespace nt +inline BooleanArrayTopic BooleanArraySubscriber::GetTopic() const { + return BooleanArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline BooleanArrayTopic BooleanArrayPublisher::GetTopic() const { + return BooleanArrayTopic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/BooleanArrayTopic.inc" +inline BooleanArrayTopic BooleanArrayEntry::GetTopic() const { + return BooleanArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/BooleanArrayTopic.inc b/ntcore/src/generated/main/native/include/networktables/BooleanArrayTopic.inc deleted file mode 100644 index 53bd5e4d23c..00000000000 --- a/ntcore/src/generated/main/native/include/networktables/BooleanArrayTopic.inc +++ /dev/null @@ -1,137 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/BooleanArrayTopic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline BooleanArraySubscriber::BooleanArraySubscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{defaultValue.begin(), defaultValue.end()} {} - -inline std::vector BooleanArraySubscriber::Get() const { - return Get(m_defaultValue); -} - -inline std::vector BooleanArraySubscriber::Get( - ParamType defaultValue) const { - return ::nt::GetBooleanArray(m_subHandle, defaultValue); -} - -inline std::span BooleanArraySubscriber::Get(wpi::SmallVectorImpl& buf) const { - return Get(buf, m_defaultValue); -} - -inline std::span BooleanArraySubscriber::Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetBooleanArray(m_subHandle, buf, defaultValue); -} - -inline TimestampedBooleanArray BooleanArraySubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline TimestampedBooleanArray BooleanArraySubscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomicBooleanArray(m_subHandle, defaultValue); -} - -inline TimestampedBooleanArrayView BooleanArraySubscriber::GetAtomic(wpi::SmallVectorImpl& buf) const { - return GetAtomic(buf, m_defaultValue); -} - -inline TimestampedBooleanArrayView BooleanArraySubscriber::GetAtomic(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetAtomicBooleanArray(m_subHandle, buf, defaultValue); -} - -inline std::vector -BooleanArraySubscriber::ReadQueue() { - return ::nt::ReadQueueBooleanArray(m_subHandle); -} - -inline BooleanArrayTopic BooleanArraySubscriber::GetTopic() const { - return BooleanArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline BooleanArrayPublisher::BooleanArrayPublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void BooleanArrayPublisher::Set(ParamType value, - int64_t time) { - ::nt::SetBooleanArray(m_pubHandle, value, time); -} - -inline void BooleanArrayPublisher::SetDefault(ParamType value) { - ::nt::SetDefaultBooleanArray(m_pubHandle, value); -} - -inline BooleanArrayTopic BooleanArrayPublisher::GetTopic() const { - return BooleanArrayTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline BooleanArrayEntry::BooleanArrayEntry( - NT_Entry handle, ParamType defaultValue) - : BooleanArraySubscriber{handle, defaultValue}, - BooleanArrayPublisher{handle} {} - -inline BooleanArrayTopic BooleanArrayEntry::GetTopic() const { - return BooleanArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void BooleanArrayEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline BooleanArraySubscriber BooleanArrayTopic::Subscribe( - std::span defaultValue, - const PubSubOptions& options) { - return BooleanArraySubscriber{ - ::nt::Subscribe(m_handle, NT_BOOLEAN_ARRAY, "boolean[]", options), - defaultValue}; -} -inline BooleanArraySubscriber BooleanArrayTopic::SubscribeEx( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return BooleanArraySubscriber{ - ::nt::Subscribe(m_handle, NT_BOOLEAN_ARRAY, typeString, options), - defaultValue}; -} - -inline BooleanArrayPublisher BooleanArrayTopic::Publish( - const PubSubOptions& options) { - return BooleanArrayPublisher{ - ::nt::Publish(m_handle, NT_BOOLEAN_ARRAY, "boolean[]", options)}; -} - -inline BooleanArrayPublisher BooleanArrayTopic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return BooleanArrayPublisher{ - ::nt::PublishEx(m_handle, NT_BOOLEAN_ARRAY, typeString, properties, options)}; -} - -inline BooleanArrayEntry BooleanArrayTopic::GetEntry( - std::span defaultValue, - const PubSubOptions& options) { - return BooleanArrayEntry{ - ::nt::GetEntry(m_handle, NT_BOOLEAN_ARRAY, "boolean[]", options), - defaultValue}; -} -inline BooleanArrayEntry BooleanArrayTopic::GetEntryEx( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return BooleanArrayEntry{ - ::nt::GetEntry(m_handle, NT_BOOLEAN_ARRAY, typeString, options), - defaultValue}; -} - -} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/BooleanTopic.h b/ntcore/src/generated/main/native/include/networktables/BooleanTopic.h index 22db06b9e1d..6da5b2943e4 100644 --- a/ntcore/src/generated/main/native/include/networktables/BooleanTopic.h +++ b/ntcore/src/generated/main/native/include/networktables/BooleanTopic.h @@ -15,7 +15,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -46,7 +48,9 @@ class BooleanSubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - BooleanSubscriber(NT_Subscriber handle, ParamType defaultValue); + BooleanSubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{defaultValue} {} /** * Get the last published value. @@ -54,7 +58,9 @@ class BooleanSubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -63,7 +69,9 @@ class BooleanSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::GetBoolean(m_subHandle, defaultValue); + } /** * Get the last published value along with its timestamp @@ -72,7 +80,9 @@ class BooleanSubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -82,7 +92,9 @@ class BooleanSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomicBoolean(m_subHandle, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -94,7 +106,9 @@ class BooleanSubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueBoolean(m_subHandle); + } /** * Get the corresponding topic. @@ -126,7 +140,7 @@ class BooleanPublisher : public Publisher { * * @param handle Native handle */ - explicit BooleanPublisher(NT_Publisher handle); + explicit BooleanPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -134,7 +148,9 @@ class BooleanPublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetBoolean(m_pubHandle, value, time); + } /** * Publish a default value. @@ -143,7 +159,9 @@ class BooleanPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultBoolean(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -178,7 +196,9 @@ class BooleanEntry final : public BooleanSubscriber, * @param handle Native handle * @param defaultValue Default value */ - BooleanEntry(NT_Entry handle, ParamType defaultValue); + BooleanEntry(NT_Entry handle, ParamType defaultValue) + : BooleanSubscriber{handle, defaultValue}, + BooleanPublisher{handle} {} /** * Determines if the native handle is valid. @@ -204,7 +224,9 @@ class BooleanEntry final : public BooleanSubscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -256,7 +278,11 @@ class BooleanTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanSubscriber{ + ::nt::Subscribe(m_handle, NT_BOOLEAN, "boolean", options), + defaultValue}; + } /** * Create a new subscriber to the topic, with specific type string. * @@ -276,7 +302,11 @@ class BooleanTopic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanSubscriber{ + ::nt::Subscribe(m_handle, NT_BOOLEAN, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. @@ -294,7 +324,10 @@ class BooleanTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanPublisher{ + ::nt::Publish(m_handle, NT_BOOLEAN, "boolean", options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -316,7 +349,10 @@ class BooleanTopic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanPublisher{ + ::nt::PublishEx(m_handle, NT_BOOLEAN, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -340,7 +376,11 @@ class BooleanTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanEntry{ + ::nt::GetEntry(m_handle, NT_BOOLEAN, "boolean", options), + defaultValue}; + } /** * Create a new entry for the topic, with specific type string. * @@ -364,10 +404,24 @@ class BooleanTopic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return BooleanEntry{ + ::nt::GetEntry(m_handle, NT_BOOLEAN, typeString, options), + defaultValue}; + } }; -} // namespace nt +inline BooleanTopic BooleanSubscriber::GetTopic() const { + return BooleanTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline BooleanTopic BooleanPublisher::GetTopic() const { + return BooleanTopic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/BooleanTopic.inc" +inline BooleanTopic BooleanEntry::GetTopic() const { + return BooleanTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/BooleanTopic.inc b/ntcore/src/generated/main/native/include/networktables/BooleanTopic.inc deleted file mode 100644 index 5b7d0999571..00000000000 --- a/ntcore/src/generated/main/native/include/networktables/BooleanTopic.inc +++ /dev/null @@ -1,121 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/BooleanTopic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline BooleanSubscriber::BooleanSubscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{defaultValue} {} - -inline bool BooleanSubscriber::Get() const { - return Get(m_defaultValue); -} - -inline bool BooleanSubscriber::Get( - ParamType defaultValue) const { - return ::nt::GetBoolean(m_subHandle, defaultValue); -} - -inline TimestampedBoolean BooleanSubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline TimestampedBoolean BooleanSubscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomicBoolean(m_subHandle, defaultValue); -} - -inline std::vector -BooleanSubscriber::ReadQueue() { - return ::nt::ReadQueueBoolean(m_subHandle); -} - -inline BooleanTopic BooleanSubscriber::GetTopic() const { - return BooleanTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline BooleanPublisher::BooleanPublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void BooleanPublisher::Set(ParamType value, - int64_t time) { - ::nt::SetBoolean(m_pubHandle, value, time); -} - -inline void BooleanPublisher::SetDefault(ParamType value) { - ::nt::SetDefaultBoolean(m_pubHandle, value); -} - -inline BooleanTopic BooleanPublisher::GetTopic() const { - return BooleanTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline BooleanEntry::BooleanEntry( - NT_Entry handle, ParamType defaultValue) - : BooleanSubscriber{handle, defaultValue}, - BooleanPublisher{handle} {} - -inline BooleanTopic BooleanEntry::GetTopic() const { - return BooleanTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void BooleanEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline BooleanSubscriber BooleanTopic::Subscribe( - bool defaultValue, - const PubSubOptions& options) { - return BooleanSubscriber{ - ::nt::Subscribe(m_handle, NT_BOOLEAN, "boolean", options), - defaultValue}; -} -inline BooleanSubscriber BooleanTopic::SubscribeEx( - std::string_view typeString, bool defaultValue, - const PubSubOptions& options) { - return BooleanSubscriber{ - ::nt::Subscribe(m_handle, NT_BOOLEAN, typeString, options), - defaultValue}; -} - -inline BooleanPublisher BooleanTopic::Publish( - const PubSubOptions& options) { - return BooleanPublisher{ - ::nt::Publish(m_handle, NT_BOOLEAN, "boolean", options)}; -} - -inline BooleanPublisher BooleanTopic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return BooleanPublisher{ - ::nt::PublishEx(m_handle, NT_BOOLEAN, typeString, properties, options)}; -} - -inline BooleanEntry BooleanTopic::GetEntry( - bool defaultValue, - const PubSubOptions& options) { - return BooleanEntry{ - ::nt::GetEntry(m_handle, NT_BOOLEAN, "boolean", options), - defaultValue}; -} -inline BooleanEntry BooleanTopic::GetEntryEx( - std::string_view typeString, bool defaultValue, - const PubSubOptions& options) { - return BooleanEntry{ - ::nt::GetEntry(m_handle, NT_BOOLEAN, typeString, options), - defaultValue}; -} - -} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/DoubleArrayTopic.h b/ntcore/src/generated/main/native/include/networktables/DoubleArrayTopic.h index 6f64d367f2c..79aba1ddbac 100644 --- a/ntcore/src/generated/main/native/include/networktables/DoubleArrayTopic.h +++ b/ntcore/src/generated/main/native/include/networktables/DoubleArrayTopic.h @@ -15,7 +15,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -50,7 +52,9 @@ class DoubleArraySubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - DoubleArraySubscriber(NT_Subscriber handle, ParamType defaultValue); + DoubleArraySubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{defaultValue.begin(), defaultValue.end()} {} /** * Get the last published value. @@ -58,7 +62,9 @@ class DoubleArraySubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -67,7 +73,9 @@ class DoubleArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::GetDoubleArray(m_subHandle, defaultValue); + } /** * Get the last published value. @@ -76,7 +84,9 @@ class DoubleArraySubscriber : public Subscriber { * @param buf storage for returned value * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf) const; + SmallRetType Get(wpi::SmallVectorImpl& buf) const { + return Get(buf, m_defaultValue); + } /** * Get the last published value. @@ -86,7 +96,9 @@ class DoubleArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const; + SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { + return nt::GetDoubleArray(m_subHandle, buf, defaultValue); + } /** * Get the last published value along with its timestamp @@ -95,7 +107,9 @@ class DoubleArraySubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -105,7 +119,9 @@ class DoubleArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomicDoubleArray(m_subHandle, defaultValue); + } /** * Get the last published value along with its timestamp. @@ -116,7 +132,9 @@ class DoubleArraySubscriber : public Subscriber { * @return timestamped value */ TimestampedValueViewType GetAtomic( - wpi::SmallVectorImpl& buf) const; + wpi::SmallVectorImpl& buf) const { + return GetAtomic(buf, m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -129,7 +147,9 @@ class DoubleArraySubscriber : public Subscriber { */ TimestampedValueViewType GetAtomic( wpi::SmallVectorImpl& buf, - ParamType defaultValue) const; + ParamType defaultValue) const { + return nt::GetAtomicDoubleArray(m_subHandle, buf, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -141,7 +161,9 @@ class DoubleArraySubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueDoubleArray(m_subHandle); + } /** * Get the corresponding topic. @@ -176,7 +198,7 @@ class DoubleArrayPublisher : public Publisher { * * @param handle Native handle */ - explicit DoubleArrayPublisher(NT_Publisher handle); + explicit DoubleArrayPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -184,7 +206,9 @@ class DoubleArrayPublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetDoubleArray(m_pubHandle, value, time); + } /** * Publish a default value. @@ -193,7 +217,9 @@ class DoubleArrayPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultDoubleArray(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -231,7 +257,9 @@ class DoubleArrayEntry final : public DoubleArraySubscriber, * @param handle Native handle * @param defaultValue Default value */ - DoubleArrayEntry(NT_Entry handle, ParamType defaultValue); + DoubleArrayEntry(NT_Entry handle, ParamType defaultValue) + : DoubleArraySubscriber{handle, defaultValue}, + DoubleArrayPublisher{handle} {} /** * Determines if the native handle is valid. @@ -257,7 +285,9 @@ class DoubleArrayEntry final : public DoubleArraySubscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -309,7 +339,11 @@ class DoubleArrayTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return DoubleArraySubscriber{ + ::nt::Subscribe(m_handle, NT_DOUBLE_ARRAY, "double[]", options), + defaultValue}; + } /** * Create a new subscriber to the topic, with specific type string. * @@ -329,7 +363,11 @@ class DoubleArrayTopic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return DoubleArraySubscriber{ + ::nt::Subscribe(m_handle, NT_DOUBLE_ARRAY, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. @@ -347,7 +385,10 @@ class DoubleArrayTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return DoubleArrayPublisher{ + ::nt::Publish(m_handle, NT_DOUBLE_ARRAY, "double[]", options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -369,7 +410,10 @@ class DoubleArrayTopic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return DoubleArrayPublisher{ + ::nt::PublishEx(m_handle, NT_DOUBLE_ARRAY, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -393,7 +437,11 @@ class DoubleArrayTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return DoubleArrayEntry{ + ::nt::GetEntry(m_handle, NT_DOUBLE_ARRAY, "double[]", options), + defaultValue}; + } /** * Create a new entry for the topic, with specific type string. * @@ -417,10 +465,24 @@ class DoubleArrayTopic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return DoubleArrayEntry{ + ::nt::GetEntry(m_handle, NT_DOUBLE_ARRAY, typeString, options), + defaultValue}; + } }; -} // namespace nt +inline DoubleArrayTopic DoubleArraySubscriber::GetTopic() const { + return DoubleArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline DoubleArrayTopic DoubleArrayPublisher::GetTopic() const { + return DoubleArrayTopic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/DoubleArrayTopic.inc" +inline DoubleArrayTopic DoubleArrayEntry::GetTopic() const { + return DoubleArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/DoubleArrayTopic.inc b/ntcore/src/generated/main/native/include/networktables/DoubleArrayTopic.inc deleted file mode 100644 index f6cb74219a3..00000000000 --- a/ntcore/src/generated/main/native/include/networktables/DoubleArrayTopic.inc +++ /dev/null @@ -1,137 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/DoubleArrayTopic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline DoubleArraySubscriber::DoubleArraySubscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{defaultValue.begin(), defaultValue.end()} {} - -inline std::vector DoubleArraySubscriber::Get() const { - return Get(m_defaultValue); -} - -inline std::vector DoubleArraySubscriber::Get( - ParamType defaultValue) const { - return ::nt::GetDoubleArray(m_subHandle, defaultValue); -} - -inline std::span DoubleArraySubscriber::Get(wpi::SmallVectorImpl& buf) const { - return Get(buf, m_defaultValue); -} - -inline std::span DoubleArraySubscriber::Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetDoubleArray(m_subHandle, buf, defaultValue); -} - -inline TimestampedDoubleArray DoubleArraySubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline TimestampedDoubleArray DoubleArraySubscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomicDoubleArray(m_subHandle, defaultValue); -} - -inline TimestampedDoubleArrayView DoubleArraySubscriber::GetAtomic(wpi::SmallVectorImpl& buf) const { - return GetAtomic(buf, m_defaultValue); -} - -inline TimestampedDoubleArrayView DoubleArraySubscriber::GetAtomic(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetAtomicDoubleArray(m_subHandle, buf, defaultValue); -} - -inline std::vector -DoubleArraySubscriber::ReadQueue() { - return ::nt::ReadQueueDoubleArray(m_subHandle); -} - -inline DoubleArrayTopic DoubleArraySubscriber::GetTopic() const { - return DoubleArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline DoubleArrayPublisher::DoubleArrayPublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void DoubleArrayPublisher::Set(ParamType value, - int64_t time) { - ::nt::SetDoubleArray(m_pubHandle, value, time); -} - -inline void DoubleArrayPublisher::SetDefault(ParamType value) { - ::nt::SetDefaultDoubleArray(m_pubHandle, value); -} - -inline DoubleArrayTopic DoubleArrayPublisher::GetTopic() const { - return DoubleArrayTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline DoubleArrayEntry::DoubleArrayEntry( - NT_Entry handle, ParamType defaultValue) - : DoubleArraySubscriber{handle, defaultValue}, - DoubleArrayPublisher{handle} {} - -inline DoubleArrayTopic DoubleArrayEntry::GetTopic() const { - return DoubleArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void DoubleArrayEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline DoubleArraySubscriber DoubleArrayTopic::Subscribe( - std::span defaultValue, - const PubSubOptions& options) { - return DoubleArraySubscriber{ - ::nt::Subscribe(m_handle, NT_DOUBLE_ARRAY, "double[]", options), - defaultValue}; -} -inline DoubleArraySubscriber DoubleArrayTopic::SubscribeEx( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return DoubleArraySubscriber{ - ::nt::Subscribe(m_handle, NT_DOUBLE_ARRAY, typeString, options), - defaultValue}; -} - -inline DoubleArrayPublisher DoubleArrayTopic::Publish( - const PubSubOptions& options) { - return DoubleArrayPublisher{ - ::nt::Publish(m_handle, NT_DOUBLE_ARRAY, "double[]", options)}; -} - -inline DoubleArrayPublisher DoubleArrayTopic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return DoubleArrayPublisher{ - ::nt::PublishEx(m_handle, NT_DOUBLE_ARRAY, typeString, properties, options)}; -} - -inline DoubleArrayEntry DoubleArrayTopic::GetEntry( - std::span defaultValue, - const PubSubOptions& options) { - return DoubleArrayEntry{ - ::nt::GetEntry(m_handle, NT_DOUBLE_ARRAY, "double[]", options), - defaultValue}; -} -inline DoubleArrayEntry DoubleArrayTopic::GetEntryEx( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return DoubleArrayEntry{ - ::nt::GetEntry(m_handle, NT_DOUBLE_ARRAY, typeString, options), - defaultValue}; -} - -} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/DoubleTopic.h b/ntcore/src/generated/main/native/include/networktables/DoubleTopic.h index bcb1751b404..5601354a2bc 100644 --- a/ntcore/src/generated/main/native/include/networktables/DoubleTopic.h +++ b/ntcore/src/generated/main/native/include/networktables/DoubleTopic.h @@ -15,7 +15,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -46,7 +48,9 @@ class DoubleSubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - DoubleSubscriber(NT_Subscriber handle, ParamType defaultValue); + DoubleSubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{defaultValue} {} /** * Get the last published value. @@ -54,7 +58,9 @@ class DoubleSubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -63,7 +69,9 @@ class DoubleSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::GetDouble(m_subHandle, defaultValue); + } /** * Get the last published value along with its timestamp @@ -72,7 +80,9 @@ class DoubleSubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -82,7 +92,9 @@ class DoubleSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomicDouble(m_subHandle, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -94,7 +106,9 @@ class DoubleSubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueDouble(m_subHandle); + } /** * Get the corresponding topic. @@ -126,7 +140,7 @@ class DoublePublisher : public Publisher { * * @param handle Native handle */ - explicit DoublePublisher(NT_Publisher handle); + explicit DoublePublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -134,7 +148,9 @@ class DoublePublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetDouble(m_pubHandle, value, time); + } /** * Publish a default value. @@ -143,7 +159,9 @@ class DoublePublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultDouble(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -178,7 +196,9 @@ class DoubleEntry final : public DoubleSubscriber, * @param handle Native handle * @param defaultValue Default value */ - DoubleEntry(NT_Entry handle, ParamType defaultValue); + DoubleEntry(NT_Entry handle, ParamType defaultValue) + : DoubleSubscriber{handle, defaultValue}, + DoublePublisher{handle} {} /** * Determines if the native handle is valid. @@ -204,7 +224,9 @@ class DoubleEntry final : public DoubleSubscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -256,7 +278,11 @@ class DoubleTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return DoubleSubscriber{ + ::nt::Subscribe(m_handle, NT_DOUBLE, "double", options), + defaultValue}; + } /** * Create a new subscriber to the topic, with specific type string. * @@ -276,7 +302,11 @@ class DoubleTopic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return DoubleSubscriber{ + ::nt::Subscribe(m_handle, NT_DOUBLE, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. @@ -294,7 +324,10 @@ class DoubleTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return DoublePublisher{ + ::nt::Publish(m_handle, NT_DOUBLE, "double", options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -316,7 +349,10 @@ class DoubleTopic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return DoublePublisher{ + ::nt::PublishEx(m_handle, NT_DOUBLE, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -340,7 +376,11 @@ class DoubleTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return DoubleEntry{ + ::nt::GetEntry(m_handle, NT_DOUBLE, "double", options), + defaultValue}; + } /** * Create a new entry for the topic, with specific type string. * @@ -364,10 +404,24 @@ class DoubleTopic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return DoubleEntry{ + ::nt::GetEntry(m_handle, NT_DOUBLE, typeString, options), + defaultValue}; + } }; -} // namespace nt +inline DoubleTopic DoubleSubscriber::GetTopic() const { + return DoubleTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline DoubleTopic DoublePublisher::GetTopic() const { + return DoubleTopic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/DoubleTopic.inc" +inline DoubleTopic DoubleEntry::GetTopic() const { + return DoubleTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/DoubleTopic.inc b/ntcore/src/generated/main/native/include/networktables/DoubleTopic.inc deleted file mode 100644 index 1ca4ec4b93b..00000000000 --- a/ntcore/src/generated/main/native/include/networktables/DoubleTopic.inc +++ /dev/null @@ -1,121 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/DoubleTopic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline DoubleSubscriber::DoubleSubscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{defaultValue} {} - -inline double DoubleSubscriber::Get() const { - return Get(m_defaultValue); -} - -inline double DoubleSubscriber::Get( - ParamType defaultValue) const { - return ::nt::GetDouble(m_subHandle, defaultValue); -} - -inline TimestampedDouble DoubleSubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline TimestampedDouble DoubleSubscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomicDouble(m_subHandle, defaultValue); -} - -inline std::vector -DoubleSubscriber::ReadQueue() { - return ::nt::ReadQueueDouble(m_subHandle); -} - -inline DoubleTopic DoubleSubscriber::GetTopic() const { - return DoubleTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline DoublePublisher::DoublePublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void DoublePublisher::Set(ParamType value, - int64_t time) { - ::nt::SetDouble(m_pubHandle, value, time); -} - -inline void DoublePublisher::SetDefault(ParamType value) { - ::nt::SetDefaultDouble(m_pubHandle, value); -} - -inline DoubleTopic DoublePublisher::GetTopic() const { - return DoubleTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline DoubleEntry::DoubleEntry( - NT_Entry handle, ParamType defaultValue) - : DoubleSubscriber{handle, defaultValue}, - DoublePublisher{handle} {} - -inline DoubleTopic DoubleEntry::GetTopic() const { - return DoubleTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void DoubleEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline DoubleSubscriber DoubleTopic::Subscribe( - double defaultValue, - const PubSubOptions& options) { - return DoubleSubscriber{ - ::nt::Subscribe(m_handle, NT_DOUBLE, "double", options), - defaultValue}; -} -inline DoubleSubscriber DoubleTopic::SubscribeEx( - std::string_view typeString, double defaultValue, - const PubSubOptions& options) { - return DoubleSubscriber{ - ::nt::Subscribe(m_handle, NT_DOUBLE, typeString, options), - defaultValue}; -} - -inline DoublePublisher DoubleTopic::Publish( - const PubSubOptions& options) { - return DoublePublisher{ - ::nt::Publish(m_handle, NT_DOUBLE, "double", options)}; -} - -inline DoublePublisher DoubleTopic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return DoublePublisher{ - ::nt::PublishEx(m_handle, NT_DOUBLE, typeString, properties, options)}; -} - -inline DoubleEntry DoubleTopic::GetEntry( - double defaultValue, - const PubSubOptions& options) { - return DoubleEntry{ - ::nt::GetEntry(m_handle, NT_DOUBLE, "double", options), - defaultValue}; -} -inline DoubleEntry DoubleTopic::GetEntryEx( - std::string_view typeString, double defaultValue, - const PubSubOptions& options) { - return DoubleEntry{ - ::nt::GetEntry(m_handle, NT_DOUBLE, typeString, options), - defaultValue}; -} - -} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/FloatArrayTopic.h b/ntcore/src/generated/main/native/include/networktables/FloatArrayTopic.h index a0d2b66b33e..c54425250d1 100644 --- a/ntcore/src/generated/main/native/include/networktables/FloatArrayTopic.h +++ b/ntcore/src/generated/main/native/include/networktables/FloatArrayTopic.h @@ -15,7 +15,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -50,7 +52,9 @@ class FloatArraySubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - FloatArraySubscriber(NT_Subscriber handle, ParamType defaultValue); + FloatArraySubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{defaultValue.begin(), defaultValue.end()} {} /** * Get the last published value. @@ -58,7 +62,9 @@ class FloatArraySubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -67,7 +73,9 @@ class FloatArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::GetFloatArray(m_subHandle, defaultValue); + } /** * Get the last published value. @@ -76,7 +84,9 @@ class FloatArraySubscriber : public Subscriber { * @param buf storage for returned value * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf) const; + SmallRetType Get(wpi::SmallVectorImpl& buf) const { + return Get(buf, m_defaultValue); + } /** * Get the last published value. @@ -86,7 +96,9 @@ class FloatArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const; + SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { + return nt::GetFloatArray(m_subHandle, buf, defaultValue); + } /** * Get the last published value along with its timestamp @@ -95,7 +107,9 @@ class FloatArraySubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -105,7 +119,9 @@ class FloatArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomicFloatArray(m_subHandle, defaultValue); + } /** * Get the last published value along with its timestamp. @@ -116,7 +132,9 @@ class FloatArraySubscriber : public Subscriber { * @return timestamped value */ TimestampedValueViewType GetAtomic( - wpi::SmallVectorImpl& buf) const; + wpi::SmallVectorImpl& buf) const { + return GetAtomic(buf, m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -129,7 +147,9 @@ class FloatArraySubscriber : public Subscriber { */ TimestampedValueViewType GetAtomic( wpi::SmallVectorImpl& buf, - ParamType defaultValue) const; + ParamType defaultValue) const { + return nt::GetAtomicFloatArray(m_subHandle, buf, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -141,7 +161,9 @@ class FloatArraySubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueFloatArray(m_subHandle); + } /** * Get the corresponding topic. @@ -176,7 +198,7 @@ class FloatArrayPublisher : public Publisher { * * @param handle Native handle */ - explicit FloatArrayPublisher(NT_Publisher handle); + explicit FloatArrayPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -184,7 +206,9 @@ class FloatArrayPublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetFloatArray(m_pubHandle, value, time); + } /** * Publish a default value. @@ -193,7 +217,9 @@ class FloatArrayPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultFloatArray(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -231,7 +257,9 @@ class FloatArrayEntry final : public FloatArraySubscriber, * @param handle Native handle * @param defaultValue Default value */ - FloatArrayEntry(NT_Entry handle, ParamType defaultValue); + FloatArrayEntry(NT_Entry handle, ParamType defaultValue) + : FloatArraySubscriber{handle, defaultValue}, + FloatArrayPublisher{handle} {} /** * Determines if the native handle is valid. @@ -257,7 +285,9 @@ class FloatArrayEntry final : public FloatArraySubscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -309,7 +339,11 @@ class FloatArrayTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatArraySubscriber{ + ::nt::Subscribe(m_handle, NT_FLOAT_ARRAY, "float[]", options), + defaultValue}; + } /** * Create a new subscriber to the topic, with specific type string. * @@ -329,7 +363,11 @@ class FloatArrayTopic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatArraySubscriber{ + ::nt::Subscribe(m_handle, NT_FLOAT_ARRAY, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. @@ -347,7 +385,10 @@ class FloatArrayTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatArrayPublisher{ + ::nt::Publish(m_handle, NT_FLOAT_ARRAY, "float[]", options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -369,7 +410,10 @@ class FloatArrayTopic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatArrayPublisher{ + ::nt::PublishEx(m_handle, NT_FLOAT_ARRAY, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -393,7 +437,11 @@ class FloatArrayTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatArrayEntry{ + ::nt::GetEntry(m_handle, NT_FLOAT_ARRAY, "float[]", options), + defaultValue}; + } /** * Create a new entry for the topic, with specific type string. * @@ -417,10 +465,24 @@ class FloatArrayTopic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatArrayEntry{ + ::nt::GetEntry(m_handle, NT_FLOAT_ARRAY, typeString, options), + defaultValue}; + } }; -} // namespace nt +inline FloatArrayTopic FloatArraySubscriber::GetTopic() const { + return FloatArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline FloatArrayTopic FloatArrayPublisher::GetTopic() const { + return FloatArrayTopic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/FloatArrayTopic.inc" +inline FloatArrayTopic FloatArrayEntry::GetTopic() const { + return FloatArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/FloatArrayTopic.inc b/ntcore/src/generated/main/native/include/networktables/FloatArrayTopic.inc deleted file mode 100644 index 3eeb112d6da..00000000000 --- a/ntcore/src/generated/main/native/include/networktables/FloatArrayTopic.inc +++ /dev/null @@ -1,137 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/FloatArrayTopic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline FloatArraySubscriber::FloatArraySubscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{defaultValue.begin(), defaultValue.end()} {} - -inline std::vector FloatArraySubscriber::Get() const { - return Get(m_defaultValue); -} - -inline std::vector FloatArraySubscriber::Get( - ParamType defaultValue) const { - return ::nt::GetFloatArray(m_subHandle, defaultValue); -} - -inline std::span FloatArraySubscriber::Get(wpi::SmallVectorImpl& buf) const { - return Get(buf, m_defaultValue); -} - -inline std::span FloatArraySubscriber::Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetFloatArray(m_subHandle, buf, defaultValue); -} - -inline TimestampedFloatArray FloatArraySubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline TimestampedFloatArray FloatArraySubscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomicFloatArray(m_subHandle, defaultValue); -} - -inline TimestampedFloatArrayView FloatArraySubscriber::GetAtomic(wpi::SmallVectorImpl& buf) const { - return GetAtomic(buf, m_defaultValue); -} - -inline TimestampedFloatArrayView FloatArraySubscriber::GetAtomic(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetAtomicFloatArray(m_subHandle, buf, defaultValue); -} - -inline std::vector -FloatArraySubscriber::ReadQueue() { - return ::nt::ReadQueueFloatArray(m_subHandle); -} - -inline FloatArrayTopic FloatArraySubscriber::GetTopic() const { - return FloatArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline FloatArrayPublisher::FloatArrayPublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void FloatArrayPublisher::Set(ParamType value, - int64_t time) { - ::nt::SetFloatArray(m_pubHandle, value, time); -} - -inline void FloatArrayPublisher::SetDefault(ParamType value) { - ::nt::SetDefaultFloatArray(m_pubHandle, value); -} - -inline FloatArrayTopic FloatArrayPublisher::GetTopic() const { - return FloatArrayTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline FloatArrayEntry::FloatArrayEntry( - NT_Entry handle, ParamType defaultValue) - : FloatArraySubscriber{handle, defaultValue}, - FloatArrayPublisher{handle} {} - -inline FloatArrayTopic FloatArrayEntry::GetTopic() const { - return FloatArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void FloatArrayEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline FloatArraySubscriber FloatArrayTopic::Subscribe( - std::span defaultValue, - const PubSubOptions& options) { - return FloatArraySubscriber{ - ::nt::Subscribe(m_handle, NT_FLOAT_ARRAY, "float[]", options), - defaultValue}; -} -inline FloatArraySubscriber FloatArrayTopic::SubscribeEx( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return FloatArraySubscriber{ - ::nt::Subscribe(m_handle, NT_FLOAT_ARRAY, typeString, options), - defaultValue}; -} - -inline FloatArrayPublisher FloatArrayTopic::Publish( - const PubSubOptions& options) { - return FloatArrayPublisher{ - ::nt::Publish(m_handle, NT_FLOAT_ARRAY, "float[]", options)}; -} - -inline FloatArrayPublisher FloatArrayTopic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return FloatArrayPublisher{ - ::nt::PublishEx(m_handle, NT_FLOAT_ARRAY, typeString, properties, options)}; -} - -inline FloatArrayEntry FloatArrayTopic::GetEntry( - std::span defaultValue, - const PubSubOptions& options) { - return FloatArrayEntry{ - ::nt::GetEntry(m_handle, NT_FLOAT_ARRAY, "float[]", options), - defaultValue}; -} -inline FloatArrayEntry FloatArrayTopic::GetEntryEx( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return FloatArrayEntry{ - ::nt::GetEntry(m_handle, NT_FLOAT_ARRAY, typeString, options), - defaultValue}; -} - -} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/FloatTopic.h b/ntcore/src/generated/main/native/include/networktables/FloatTopic.h index 9a838348765..1e402837dd4 100644 --- a/ntcore/src/generated/main/native/include/networktables/FloatTopic.h +++ b/ntcore/src/generated/main/native/include/networktables/FloatTopic.h @@ -15,7 +15,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -46,7 +48,9 @@ class FloatSubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - FloatSubscriber(NT_Subscriber handle, ParamType defaultValue); + FloatSubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{defaultValue} {} /** * Get the last published value. @@ -54,7 +58,9 @@ class FloatSubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -63,7 +69,9 @@ class FloatSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::GetFloat(m_subHandle, defaultValue); + } /** * Get the last published value along with its timestamp @@ -72,7 +80,9 @@ class FloatSubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -82,7 +92,9 @@ class FloatSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomicFloat(m_subHandle, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -94,7 +106,9 @@ class FloatSubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueFloat(m_subHandle); + } /** * Get the corresponding topic. @@ -126,7 +140,7 @@ class FloatPublisher : public Publisher { * * @param handle Native handle */ - explicit FloatPublisher(NT_Publisher handle); + explicit FloatPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -134,7 +148,9 @@ class FloatPublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetFloat(m_pubHandle, value, time); + } /** * Publish a default value. @@ -143,7 +159,9 @@ class FloatPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultFloat(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -178,7 +196,9 @@ class FloatEntry final : public FloatSubscriber, * @param handle Native handle * @param defaultValue Default value */ - FloatEntry(NT_Entry handle, ParamType defaultValue); + FloatEntry(NT_Entry handle, ParamType defaultValue) + : FloatSubscriber{handle, defaultValue}, + FloatPublisher{handle} {} /** * Determines if the native handle is valid. @@ -204,7 +224,9 @@ class FloatEntry final : public FloatSubscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -256,7 +278,11 @@ class FloatTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatSubscriber{ + ::nt::Subscribe(m_handle, NT_FLOAT, "float", options), + defaultValue}; + } /** * Create a new subscriber to the topic, with specific type string. * @@ -276,7 +302,11 @@ class FloatTopic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatSubscriber{ + ::nt::Subscribe(m_handle, NT_FLOAT, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. @@ -294,7 +324,10 @@ class FloatTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatPublisher{ + ::nt::Publish(m_handle, NT_FLOAT, "float", options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -316,7 +349,10 @@ class FloatTopic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatPublisher{ + ::nt::PublishEx(m_handle, NT_FLOAT, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -340,7 +376,11 @@ class FloatTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatEntry{ + ::nt::GetEntry(m_handle, NT_FLOAT, "float", options), + defaultValue}; + } /** * Create a new entry for the topic, with specific type string. * @@ -364,10 +404,24 @@ class FloatTopic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return FloatEntry{ + ::nt::GetEntry(m_handle, NT_FLOAT, typeString, options), + defaultValue}; + } }; -} // namespace nt +inline FloatTopic FloatSubscriber::GetTopic() const { + return FloatTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline FloatTopic FloatPublisher::GetTopic() const { + return FloatTopic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/FloatTopic.inc" +inline FloatTopic FloatEntry::GetTopic() const { + return FloatTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/FloatTopic.inc b/ntcore/src/generated/main/native/include/networktables/FloatTopic.inc deleted file mode 100644 index 3f8f4484865..00000000000 --- a/ntcore/src/generated/main/native/include/networktables/FloatTopic.inc +++ /dev/null @@ -1,121 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/FloatTopic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline FloatSubscriber::FloatSubscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{defaultValue} {} - -inline float FloatSubscriber::Get() const { - return Get(m_defaultValue); -} - -inline float FloatSubscriber::Get( - ParamType defaultValue) const { - return ::nt::GetFloat(m_subHandle, defaultValue); -} - -inline TimestampedFloat FloatSubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline TimestampedFloat FloatSubscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomicFloat(m_subHandle, defaultValue); -} - -inline std::vector -FloatSubscriber::ReadQueue() { - return ::nt::ReadQueueFloat(m_subHandle); -} - -inline FloatTopic FloatSubscriber::GetTopic() const { - return FloatTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline FloatPublisher::FloatPublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void FloatPublisher::Set(ParamType value, - int64_t time) { - ::nt::SetFloat(m_pubHandle, value, time); -} - -inline void FloatPublisher::SetDefault(ParamType value) { - ::nt::SetDefaultFloat(m_pubHandle, value); -} - -inline FloatTopic FloatPublisher::GetTopic() const { - return FloatTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline FloatEntry::FloatEntry( - NT_Entry handle, ParamType defaultValue) - : FloatSubscriber{handle, defaultValue}, - FloatPublisher{handle} {} - -inline FloatTopic FloatEntry::GetTopic() const { - return FloatTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void FloatEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline FloatSubscriber FloatTopic::Subscribe( - float defaultValue, - const PubSubOptions& options) { - return FloatSubscriber{ - ::nt::Subscribe(m_handle, NT_FLOAT, "float", options), - defaultValue}; -} -inline FloatSubscriber FloatTopic::SubscribeEx( - std::string_view typeString, float defaultValue, - const PubSubOptions& options) { - return FloatSubscriber{ - ::nt::Subscribe(m_handle, NT_FLOAT, typeString, options), - defaultValue}; -} - -inline FloatPublisher FloatTopic::Publish( - const PubSubOptions& options) { - return FloatPublisher{ - ::nt::Publish(m_handle, NT_FLOAT, "float", options)}; -} - -inline FloatPublisher FloatTopic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return FloatPublisher{ - ::nt::PublishEx(m_handle, NT_FLOAT, typeString, properties, options)}; -} - -inline FloatEntry FloatTopic::GetEntry( - float defaultValue, - const PubSubOptions& options) { - return FloatEntry{ - ::nt::GetEntry(m_handle, NT_FLOAT, "float", options), - defaultValue}; -} -inline FloatEntry FloatTopic::GetEntryEx( - std::string_view typeString, float defaultValue, - const PubSubOptions& options) { - return FloatEntry{ - ::nt::GetEntry(m_handle, NT_FLOAT, typeString, options), - defaultValue}; -} - -} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/IntegerArrayTopic.h b/ntcore/src/generated/main/native/include/networktables/IntegerArrayTopic.h index a99823acd8c..3063d4cc44b 100644 --- a/ntcore/src/generated/main/native/include/networktables/IntegerArrayTopic.h +++ b/ntcore/src/generated/main/native/include/networktables/IntegerArrayTopic.h @@ -15,7 +15,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -50,7 +52,9 @@ class IntegerArraySubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - IntegerArraySubscriber(NT_Subscriber handle, ParamType defaultValue); + IntegerArraySubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{defaultValue.begin(), defaultValue.end()} {} /** * Get the last published value. @@ -58,7 +62,9 @@ class IntegerArraySubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -67,7 +73,9 @@ class IntegerArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::GetIntegerArray(m_subHandle, defaultValue); + } /** * Get the last published value. @@ -76,7 +84,9 @@ class IntegerArraySubscriber : public Subscriber { * @param buf storage for returned value * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf) const; + SmallRetType Get(wpi::SmallVectorImpl& buf) const { + return Get(buf, m_defaultValue); + } /** * Get the last published value. @@ -86,7 +96,9 @@ class IntegerArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const; + SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { + return nt::GetIntegerArray(m_subHandle, buf, defaultValue); + } /** * Get the last published value along with its timestamp @@ -95,7 +107,9 @@ class IntegerArraySubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -105,7 +119,9 @@ class IntegerArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomicIntegerArray(m_subHandle, defaultValue); + } /** * Get the last published value along with its timestamp. @@ -116,7 +132,9 @@ class IntegerArraySubscriber : public Subscriber { * @return timestamped value */ TimestampedValueViewType GetAtomic( - wpi::SmallVectorImpl& buf) const; + wpi::SmallVectorImpl& buf) const { + return GetAtomic(buf, m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -129,7 +147,9 @@ class IntegerArraySubscriber : public Subscriber { */ TimestampedValueViewType GetAtomic( wpi::SmallVectorImpl& buf, - ParamType defaultValue) const; + ParamType defaultValue) const { + return nt::GetAtomicIntegerArray(m_subHandle, buf, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -141,7 +161,9 @@ class IntegerArraySubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueIntegerArray(m_subHandle); + } /** * Get the corresponding topic. @@ -176,7 +198,7 @@ class IntegerArrayPublisher : public Publisher { * * @param handle Native handle */ - explicit IntegerArrayPublisher(NT_Publisher handle); + explicit IntegerArrayPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -184,7 +206,9 @@ class IntegerArrayPublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetIntegerArray(m_pubHandle, value, time); + } /** * Publish a default value. @@ -193,7 +217,9 @@ class IntegerArrayPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultIntegerArray(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -231,7 +257,9 @@ class IntegerArrayEntry final : public IntegerArraySubscriber, * @param handle Native handle * @param defaultValue Default value */ - IntegerArrayEntry(NT_Entry handle, ParamType defaultValue); + IntegerArrayEntry(NT_Entry handle, ParamType defaultValue) + : IntegerArraySubscriber{handle, defaultValue}, + IntegerArrayPublisher{handle} {} /** * Determines if the native handle is valid. @@ -257,7 +285,9 @@ class IntegerArrayEntry final : public IntegerArraySubscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -309,7 +339,11 @@ class IntegerArrayTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerArraySubscriber{ + ::nt::Subscribe(m_handle, NT_INTEGER_ARRAY, "int[]", options), + defaultValue}; + } /** * Create a new subscriber to the topic, with specific type string. * @@ -329,7 +363,11 @@ class IntegerArrayTopic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerArraySubscriber{ + ::nt::Subscribe(m_handle, NT_INTEGER_ARRAY, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. @@ -347,7 +385,10 @@ class IntegerArrayTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerArrayPublisher{ + ::nt::Publish(m_handle, NT_INTEGER_ARRAY, "int[]", options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -369,7 +410,10 @@ class IntegerArrayTopic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerArrayPublisher{ + ::nt::PublishEx(m_handle, NT_INTEGER_ARRAY, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -393,7 +437,11 @@ class IntegerArrayTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerArrayEntry{ + ::nt::GetEntry(m_handle, NT_INTEGER_ARRAY, "int[]", options), + defaultValue}; + } /** * Create a new entry for the topic, with specific type string. * @@ -417,10 +465,24 @@ class IntegerArrayTopic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerArrayEntry{ + ::nt::GetEntry(m_handle, NT_INTEGER_ARRAY, typeString, options), + defaultValue}; + } }; -} // namespace nt +inline IntegerArrayTopic IntegerArraySubscriber::GetTopic() const { + return IntegerArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline IntegerArrayTopic IntegerArrayPublisher::GetTopic() const { + return IntegerArrayTopic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/IntegerArrayTopic.inc" +inline IntegerArrayTopic IntegerArrayEntry::GetTopic() const { + return IntegerArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/IntegerArrayTopic.inc b/ntcore/src/generated/main/native/include/networktables/IntegerArrayTopic.inc deleted file mode 100644 index f4156a49433..00000000000 --- a/ntcore/src/generated/main/native/include/networktables/IntegerArrayTopic.inc +++ /dev/null @@ -1,137 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/IntegerArrayTopic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline IntegerArraySubscriber::IntegerArraySubscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{defaultValue.begin(), defaultValue.end()} {} - -inline std::vector IntegerArraySubscriber::Get() const { - return Get(m_defaultValue); -} - -inline std::vector IntegerArraySubscriber::Get( - ParamType defaultValue) const { - return ::nt::GetIntegerArray(m_subHandle, defaultValue); -} - -inline std::span IntegerArraySubscriber::Get(wpi::SmallVectorImpl& buf) const { - return Get(buf, m_defaultValue); -} - -inline std::span IntegerArraySubscriber::Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetIntegerArray(m_subHandle, buf, defaultValue); -} - -inline TimestampedIntegerArray IntegerArraySubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline TimestampedIntegerArray IntegerArraySubscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomicIntegerArray(m_subHandle, defaultValue); -} - -inline TimestampedIntegerArrayView IntegerArraySubscriber::GetAtomic(wpi::SmallVectorImpl& buf) const { - return GetAtomic(buf, m_defaultValue); -} - -inline TimestampedIntegerArrayView IntegerArraySubscriber::GetAtomic(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetAtomicIntegerArray(m_subHandle, buf, defaultValue); -} - -inline std::vector -IntegerArraySubscriber::ReadQueue() { - return ::nt::ReadQueueIntegerArray(m_subHandle); -} - -inline IntegerArrayTopic IntegerArraySubscriber::GetTopic() const { - return IntegerArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline IntegerArrayPublisher::IntegerArrayPublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void IntegerArrayPublisher::Set(ParamType value, - int64_t time) { - ::nt::SetIntegerArray(m_pubHandle, value, time); -} - -inline void IntegerArrayPublisher::SetDefault(ParamType value) { - ::nt::SetDefaultIntegerArray(m_pubHandle, value); -} - -inline IntegerArrayTopic IntegerArrayPublisher::GetTopic() const { - return IntegerArrayTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline IntegerArrayEntry::IntegerArrayEntry( - NT_Entry handle, ParamType defaultValue) - : IntegerArraySubscriber{handle, defaultValue}, - IntegerArrayPublisher{handle} {} - -inline IntegerArrayTopic IntegerArrayEntry::GetTopic() const { - return IntegerArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void IntegerArrayEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline IntegerArraySubscriber IntegerArrayTopic::Subscribe( - std::span defaultValue, - const PubSubOptions& options) { - return IntegerArraySubscriber{ - ::nt::Subscribe(m_handle, NT_INTEGER_ARRAY, "int[]", options), - defaultValue}; -} -inline IntegerArraySubscriber IntegerArrayTopic::SubscribeEx( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return IntegerArraySubscriber{ - ::nt::Subscribe(m_handle, NT_INTEGER_ARRAY, typeString, options), - defaultValue}; -} - -inline IntegerArrayPublisher IntegerArrayTopic::Publish( - const PubSubOptions& options) { - return IntegerArrayPublisher{ - ::nt::Publish(m_handle, NT_INTEGER_ARRAY, "int[]", options)}; -} - -inline IntegerArrayPublisher IntegerArrayTopic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return IntegerArrayPublisher{ - ::nt::PublishEx(m_handle, NT_INTEGER_ARRAY, typeString, properties, options)}; -} - -inline IntegerArrayEntry IntegerArrayTopic::GetEntry( - std::span defaultValue, - const PubSubOptions& options) { - return IntegerArrayEntry{ - ::nt::GetEntry(m_handle, NT_INTEGER_ARRAY, "int[]", options), - defaultValue}; -} -inline IntegerArrayEntry IntegerArrayTopic::GetEntryEx( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return IntegerArrayEntry{ - ::nt::GetEntry(m_handle, NT_INTEGER_ARRAY, typeString, options), - defaultValue}; -} - -} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/IntegerTopic.h b/ntcore/src/generated/main/native/include/networktables/IntegerTopic.h index 0d5ab21492c..f0576e9ddeb 100644 --- a/ntcore/src/generated/main/native/include/networktables/IntegerTopic.h +++ b/ntcore/src/generated/main/native/include/networktables/IntegerTopic.h @@ -15,7 +15,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -46,7 +48,9 @@ class IntegerSubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - IntegerSubscriber(NT_Subscriber handle, ParamType defaultValue); + IntegerSubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{defaultValue} {} /** * Get the last published value. @@ -54,7 +58,9 @@ class IntegerSubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -63,7 +69,9 @@ class IntegerSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::GetInteger(m_subHandle, defaultValue); + } /** * Get the last published value along with its timestamp @@ -72,7 +80,9 @@ class IntegerSubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -82,7 +92,9 @@ class IntegerSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomicInteger(m_subHandle, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -94,7 +106,9 @@ class IntegerSubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueInteger(m_subHandle); + } /** * Get the corresponding topic. @@ -126,7 +140,7 @@ class IntegerPublisher : public Publisher { * * @param handle Native handle */ - explicit IntegerPublisher(NT_Publisher handle); + explicit IntegerPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -134,7 +148,9 @@ class IntegerPublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetInteger(m_pubHandle, value, time); + } /** * Publish a default value. @@ -143,7 +159,9 @@ class IntegerPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultInteger(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -178,7 +196,9 @@ class IntegerEntry final : public IntegerSubscriber, * @param handle Native handle * @param defaultValue Default value */ - IntegerEntry(NT_Entry handle, ParamType defaultValue); + IntegerEntry(NT_Entry handle, ParamType defaultValue) + : IntegerSubscriber{handle, defaultValue}, + IntegerPublisher{handle} {} /** * Determines if the native handle is valid. @@ -204,7 +224,9 @@ class IntegerEntry final : public IntegerSubscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -256,7 +278,11 @@ class IntegerTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerSubscriber{ + ::nt::Subscribe(m_handle, NT_INTEGER, "int", options), + defaultValue}; + } /** * Create a new subscriber to the topic, with specific type string. * @@ -276,7 +302,11 @@ class IntegerTopic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerSubscriber{ + ::nt::Subscribe(m_handle, NT_INTEGER, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. @@ -294,7 +324,10 @@ class IntegerTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerPublisher{ + ::nt::Publish(m_handle, NT_INTEGER, "int", options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -316,7 +349,10 @@ class IntegerTopic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerPublisher{ + ::nt::PublishEx(m_handle, NT_INTEGER, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -340,7 +376,11 @@ class IntegerTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerEntry{ + ::nt::GetEntry(m_handle, NT_INTEGER, "int", options), + defaultValue}; + } /** * Create a new entry for the topic, with specific type string. * @@ -364,10 +404,24 @@ class IntegerTopic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return IntegerEntry{ + ::nt::GetEntry(m_handle, NT_INTEGER, typeString, options), + defaultValue}; + } }; -} // namespace nt +inline IntegerTopic IntegerSubscriber::GetTopic() const { + return IntegerTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline IntegerTopic IntegerPublisher::GetTopic() const { + return IntegerTopic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/IntegerTopic.inc" +inline IntegerTopic IntegerEntry::GetTopic() const { + return IntegerTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/IntegerTopic.inc b/ntcore/src/generated/main/native/include/networktables/IntegerTopic.inc deleted file mode 100644 index 2d58adc1633..00000000000 --- a/ntcore/src/generated/main/native/include/networktables/IntegerTopic.inc +++ /dev/null @@ -1,121 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/IntegerTopic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline IntegerSubscriber::IntegerSubscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{defaultValue} {} - -inline int64_t IntegerSubscriber::Get() const { - return Get(m_defaultValue); -} - -inline int64_t IntegerSubscriber::Get( - ParamType defaultValue) const { - return ::nt::GetInteger(m_subHandle, defaultValue); -} - -inline TimestampedInteger IntegerSubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline TimestampedInteger IntegerSubscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomicInteger(m_subHandle, defaultValue); -} - -inline std::vector -IntegerSubscriber::ReadQueue() { - return ::nt::ReadQueueInteger(m_subHandle); -} - -inline IntegerTopic IntegerSubscriber::GetTopic() const { - return IntegerTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline IntegerPublisher::IntegerPublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void IntegerPublisher::Set(ParamType value, - int64_t time) { - ::nt::SetInteger(m_pubHandle, value, time); -} - -inline void IntegerPublisher::SetDefault(ParamType value) { - ::nt::SetDefaultInteger(m_pubHandle, value); -} - -inline IntegerTopic IntegerPublisher::GetTopic() const { - return IntegerTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline IntegerEntry::IntegerEntry( - NT_Entry handle, ParamType defaultValue) - : IntegerSubscriber{handle, defaultValue}, - IntegerPublisher{handle} {} - -inline IntegerTopic IntegerEntry::GetTopic() const { - return IntegerTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void IntegerEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline IntegerSubscriber IntegerTopic::Subscribe( - int64_t defaultValue, - const PubSubOptions& options) { - return IntegerSubscriber{ - ::nt::Subscribe(m_handle, NT_INTEGER, "int", options), - defaultValue}; -} -inline IntegerSubscriber IntegerTopic::SubscribeEx( - std::string_view typeString, int64_t defaultValue, - const PubSubOptions& options) { - return IntegerSubscriber{ - ::nt::Subscribe(m_handle, NT_INTEGER, typeString, options), - defaultValue}; -} - -inline IntegerPublisher IntegerTopic::Publish( - const PubSubOptions& options) { - return IntegerPublisher{ - ::nt::Publish(m_handle, NT_INTEGER, "int", options)}; -} - -inline IntegerPublisher IntegerTopic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return IntegerPublisher{ - ::nt::PublishEx(m_handle, NT_INTEGER, typeString, properties, options)}; -} - -inline IntegerEntry IntegerTopic::GetEntry( - int64_t defaultValue, - const PubSubOptions& options) { - return IntegerEntry{ - ::nt::GetEntry(m_handle, NT_INTEGER, "int", options), - defaultValue}; -} -inline IntegerEntry IntegerTopic::GetEntryEx( - std::string_view typeString, int64_t defaultValue, - const PubSubOptions& options) { - return IntegerEntry{ - ::nt::GetEntry(m_handle, NT_INTEGER, typeString, options), - defaultValue}; -} - -} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/RawTopic.h b/ntcore/src/generated/main/native/include/networktables/RawTopic.h index e124fe1db68..b42dfe58db7 100644 --- a/ntcore/src/generated/main/native/include/networktables/RawTopic.h +++ b/ntcore/src/generated/main/native/include/networktables/RawTopic.h @@ -15,7 +15,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -50,7 +52,9 @@ class RawSubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - RawSubscriber(NT_Subscriber handle, ParamType defaultValue); + RawSubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{defaultValue.begin(), defaultValue.end()} {} /** * Get the last published value. @@ -58,7 +62,9 @@ class RawSubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -67,7 +73,9 @@ class RawSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::GetRaw(m_subHandle, defaultValue); + } /** * Get the last published value. @@ -76,7 +84,9 @@ class RawSubscriber : public Subscriber { * @param buf storage for returned value * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf) const; + SmallRetType Get(wpi::SmallVectorImpl& buf) const { + return Get(buf, m_defaultValue); + } /** * Get the last published value. @@ -86,7 +96,9 @@ class RawSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const; + SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { + return nt::GetRaw(m_subHandle, buf, defaultValue); + } /** * Get the last published value along with its timestamp @@ -95,7 +107,9 @@ class RawSubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -105,7 +119,9 @@ class RawSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomicRaw(m_subHandle, defaultValue); + } /** * Get the last published value along with its timestamp. @@ -116,7 +132,9 @@ class RawSubscriber : public Subscriber { * @return timestamped value */ TimestampedValueViewType GetAtomic( - wpi::SmallVectorImpl& buf) const; + wpi::SmallVectorImpl& buf) const { + return GetAtomic(buf, m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -129,7 +147,9 @@ class RawSubscriber : public Subscriber { */ TimestampedValueViewType GetAtomic( wpi::SmallVectorImpl& buf, - ParamType defaultValue) const; + ParamType defaultValue) const { + return nt::GetAtomicRaw(m_subHandle, buf, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -141,7 +161,9 @@ class RawSubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueRaw(m_subHandle); + } /** * Get the corresponding topic. @@ -176,7 +198,7 @@ class RawPublisher : public Publisher { * * @param handle Native handle */ - explicit RawPublisher(NT_Publisher handle); + explicit RawPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -184,7 +206,9 @@ class RawPublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetRaw(m_pubHandle, value, time); + } /** * Publish a default value. @@ -193,7 +217,9 @@ class RawPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultRaw(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -231,7 +257,9 @@ class RawEntry final : public RawSubscriber, * @param handle Native handle * @param defaultValue Default value */ - RawEntry(NT_Entry handle, ParamType defaultValue); + RawEntry(NT_Entry handle, ParamType defaultValue) + : RawSubscriber{handle, defaultValue}, + RawPublisher{handle} {} /** * Determines if the native handle is valid. @@ -257,7 +285,9 @@ class RawEntry final : public RawSubscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -309,7 +339,11 @@ class RawTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return RawSubscriber{ + ::nt::Subscribe(m_handle, NT_RAW, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. * @@ -328,7 +362,10 @@ class RawTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(std::string_view typeString, const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(std::string_view typeString, const PubSubOptions& options = kDefaultPubSubOptions) { + return RawPublisher{ + ::nt::Publish(m_handle, NT_RAW, typeString, options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -350,7 +387,10 @@ class RawTopic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return RawPublisher{ + ::nt::PublishEx(m_handle, NT_RAW, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -376,9 +416,23 @@ class RawTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return RawEntry{ + ::nt::GetEntry(m_handle, NT_RAW, typeString, options), + defaultValue}; + } }; -} // namespace nt +inline RawTopic RawSubscriber::GetTopic() const { + return RawTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline RawTopic RawPublisher::GetTopic() const { + return RawTopic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/RawTopic.inc" +inline RawTopic RawEntry::GetTopic() const { + return RawTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/RawTopic.inc b/ntcore/src/generated/main/native/include/networktables/RawTopic.inc deleted file mode 100644 index e0c7e61abc4..00000000000 --- a/ntcore/src/generated/main/native/include/networktables/RawTopic.inc +++ /dev/null @@ -1,121 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/RawTopic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline RawSubscriber::RawSubscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{defaultValue.begin(), defaultValue.end()} {} - -inline std::vector RawSubscriber::Get() const { - return Get(m_defaultValue); -} - -inline std::vector RawSubscriber::Get( - ParamType defaultValue) const { - return ::nt::GetRaw(m_subHandle, defaultValue); -} - -inline std::span RawSubscriber::Get(wpi::SmallVectorImpl& buf) const { - return Get(buf, m_defaultValue); -} - -inline std::span RawSubscriber::Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetRaw(m_subHandle, buf, defaultValue); -} - -inline TimestampedRaw RawSubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline TimestampedRaw RawSubscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomicRaw(m_subHandle, defaultValue); -} - -inline TimestampedRawView RawSubscriber::GetAtomic(wpi::SmallVectorImpl& buf) const { - return GetAtomic(buf, m_defaultValue); -} - -inline TimestampedRawView RawSubscriber::GetAtomic(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetAtomicRaw(m_subHandle, buf, defaultValue); -} - -inline std::vector -RawSubscriber::ReadQueue() { - return ::nt::ReadQueueRaw(m_subHandle); -} - -inline RawTopic RawSubscriber::GetTopic() const { - return RawTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline RawPublisher::RawPublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void RawPublisher::Set(ParamType value, - int64_t time) { - ::nt::SetRaw(m_pubHandle, value, time); -} - -inline void RawPublisher::SetDefault(ParamType value) { - ::nt::SetDefaultRaw(m_pubHandle, value); -} - -inline RawTopic RawPublisher::GetTopic() const { - return RawTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline RawEntry::RawEntry( - NT_Entry handle, ParamType defaultValue) - : RawSubscriber{handle, defaultValue}, - RawPublisher{handle} {} - -inline RawTopic RawEntry::GetTopic() const { - return RawTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void RawEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline RawSubscriber RawTopic::Subscribe( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return RawSubscriber{ - ::nt::Subscribe(m_handle, NT_RAW, typeString, options), - defaultValue}; -} -inline RawPublisher RawTopic::Publish( - std::string_view typeString, const PubSubOptions& options) { - return RawPublisher{ - ::nt::Publish(m_handle, NT_RAW, typeString, options)}; -} - -inline RawPublisher RawTopic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return RawPublisher{ - ::nt::PublishEx(m_handle, NT_RAW, typeString, properties, options)}; -} - -inline RawEntry RawTopic::GetEntry( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return RawEntry{ - ::nt::GetEntry(m_handle, NT_RAW, typeString, options), - defaultValue}; -} -} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/StringArrayTopic.h b/ntcore/src/generated/main/native/include/networktables/StringArrayTopic.h index 9339521002c..9c36bac3f36 100644 --- a/ntcore/src/generated/main/native/include/networktables/StringArrayTopic.h +++ b/ntcore/src/generated/main/native/include/networktables/StringArrayTopic.h @@ -15,7 +15,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -46,7 +48,9 @@ class StringArraySubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - StringArraySubscriber(NT_Subscriber handle, ParamType defaultValue); + StringArraySubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{defaultValue.begin(), defaultValue.end()} {} /** * Get the last published value. @@ -54,7 +58,9 @@ class StringArraySubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -63,7 +69,9 @@ class StringArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::GetStringArray(m_subHandle, defaultValue); + } /** * Get the last published value along with its timestamp @@ -72,7 +80,9 @@ class StringArraySubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -82,7 +92,9 @@ class StringArraySubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomicStringArray(m_subHandle, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -94,7 +106,9 @@ class StringArraySubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueStringArray(m_subHandle); + } /** * Get the corresponding topic. @@ -126,7 +140,7 @@ class StringArrayPublisher : public Publisher { * * @param handle Native handle */ - explicit StringArrayPublisher(NT_Publisher handle); + explicit StringArrayPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -134,7 +148,9 @@ class StringArrayPublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetStringArray(m_pubHandle, value, time); + } /** * Publish a default value. @@ -143,7 +159,9 @@ class StringArrayPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultStringArray(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -178,7 +196,9 @@ class StringArrayEntry final : public StringArraySubscriber, * @param handle Native handle * @param defaultValue Default value */ - StringArrayEntry(NT_Entry handle, ParamType defaultValue); + StringArrayEntry(NT_Entry handle, ParamType defaultValue) + : StringArraySubscriber{handle, defaultValue}, + StringArrayPublisher{handle} {} /** * Determines if the native handle is valid. @@ -204,7 +224,9 @@ class StringArrayEntry final : public StringArraySubscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -256,7 +278,11 @@ class StringArrayTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return StringArraySubscriber{ + ::nt::Subscribe(m_handle, NT_STRING_ARRAY, "string[]", options), + defaultValue}; + } /** * Create a new subscriber to the topic, with specific type string. * @@ -276,7 +302,11 @@ class StringArrayTopic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return StringArraySubscriber{ + ::nt::Subscribe(m_handle, NT_STRING_ARRAY, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. @@ -294,7 +324,10 @@ class StringArrayTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return StringArrayPublisher{ + ::nt::Publish(m_handle, NT_STRING_ARRAY, "string[]", options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -316,7 +349,10 @@ class StringArrayTopic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return StringArrayPublisher{ + ::nt::PublishEx(m_handle, NT_STRING_ARRAY, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -340,7 +376,11 @@ class StringArrayTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return StringArrayEntry{ + ::nt::GetEntry(m_handle, NT_STRING_ARRAY, "string[]", options), + defaultValue}; + } /** * Create a new entry for the topic, with specific type string. * @@ -364,10 +404,24 @@ class StringArrayTopic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return StringArrayEntry{ + ::nt::GetEntry(m_handle, NT_STRING_ARRAY, typeString, options), + defaultValue}; + } }; -} // namespace nt +inline StringArrayTopic StringArraySubscriber::GetTopic() const { + return StringArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline StringArrayTopic StringArrayPublisher::GetTopic() const { + return StringArrayTopic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/StringArrayTopic.inc" +inline StringArrayTopic StringArrayEntry::GetTopic() const { + return StringArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/StringArrayTopic.inc b/ntcore/src/generated/main/native/include/networktables/StringArrayTopic.inc deleted file mode 100644 index d6b20a2ca60..00000000000 --- a/ntcore/src/generated/main/native/include/networktables/StringArrayTopic.inc +++ /dev/null @@ -1,121 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/StringArrayTopic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline StringArraySubscriber::StringArraySubscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{defaultValue.begin(), defaultValue.end()} {} - -inline std::vector StringArraySubscriber::Get() const { - return Get(m_defaultValue); -} - -inline std::vector StringArraySubscriber::Get( - ParamType defaultValue) const { - return ::nt::GetStringArray(m_subHandle, defaultValue); -} - -inline TimestampedStringArray StringArraySubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline TimestampedStringArray StringArraySubscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomicStringArray(m_subHandle, defaultValue); -} - -inline std::vector -StringArraySubscriber::ReadQueue() { - return ::nt::ReadQueueStringArray(m_subHandle); -} - -inline StringArrayTopic StringArraySubscriber::GetTopic() const { - return StringArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline StringArrayPublisher::StringArrayPublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void StringArrayPublisher::Set(ParamType value, - int64_t time) { - ::nt::SetStringArray(m_pubHandle, value, time); -} - -inline void StringArrayPublisher::SetDefault(ParamType value) { - ::nt::SetDefaultStringArray(m_pubHandle, value); -} - -inline StringArrayTopic StringArrayPublisher::GetTopic() const { - return StringArrayTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline StringArrayEntry::StringArrayEntry( - NT_Entry handle, ParamType defaultValue) - : StringArraySubscriber{handle, defaultValue}, - StringArrayPublisher{handle} {} - -inline StringArrayTopic StringArrayEntry::GetTopic() const { - return StringArrayTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void StringArrayEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline StringArraySubscriber StringArrayTopic::Subscribe( - std::span defaultValue, - const PubSubOptions& options) { - return StringArraySubscriber{ - ::nt::Subscribe(m_handle, NT_STRING_ARRAY, "string[]", options), - defaultValue}; -} -inline StringArraySubscriber StringArrayTopic::SubscribeEx( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return StringArraySubscriber{ - ::nt::Subscribe(m_handle, NT_STRING_ARRAY, typeString, options), - defaultValue}; -} - -inline StringArrayPublisher StringArrayTopic::Publish( - const PubSubOptions& options) { - return StringArrayPublisher{ - ::nt::Publish(m_handle, NT_STRING_ARRAY, "string[]", options)}; -} - -inline StringArrayPublisher StringArrayTopic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return StringArrayPublisher{ - ::nt::PublishEx(m_handle, NT_STRING_ARRAY, typeString, properties, options)}; -} - -inline StringArrayEntry StringArrayTopic::GetEntry( - std::span defaultValue, - const PubSubOptions& options) { - return StringArrayEntry{ - ::nt::GetEntry(m_handle, NT_STRING_ARRAY, "string[]", options), - defaultValue}; -} -inline StringArrayEntry StringArrayTopic::GetEntryEx( - std::string_view typeString, std::span defaultValue, - const PubSubOptions& options) { - return StringArrayEntry{ - ::nt::GetEntry(m_handle, NT_STRING_ARRAY, typeString, options), - defaultValue}; -} - -} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/StringTopic.h b/ntcore/src/generated/main/native/include/networktables/StringTopic.h index 3e0ff87545b..2e65a1bbb78 100644 --- a/ntcore/src/generated/main/native/include/networktables/StringTopic.h +++ b/ntcore/src/generated/main/native/include/networktables/StringTopic.h @@ -17,7 +17,9 @@ #include +#include "networktables/NetworkTableType.h" #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace wpi { template @@ -52,7 +54,9 @@ class StringSubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - StringSubscriber(NT_Subscriber handle, ParamType defaultValue); + StringSubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, + m_defaultValue{defaultValue} {} /** * Get the last published value. @@ -60,7 +64,9 @@ class StringSubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { + return Get(m_defaultValue); + } /** * Get the last published value. @@ -69,7 +75,9 @@ class StringSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return ::nt::GetString(m_subHandle, defaultValue); + } /** * Get the last published value. @@ -78,7 +86,9 @@ class StringSubscriber : public Subscriber { * @param buf storage for returned value * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf) const; + SmallRetType Get(wpi::SmallVectorImpl& buf) const { + return Get(buf, m_defaultValue); + } /** * Get the last published value. @@ -88,7 +98,9 @@ class StringSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const; + SmallRetType Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { + return nt::GetString(m_subHandle, buf, defaultValue); + } /** * Get the last published value along with its timestamp @@ -97,7 +109,9 @@ class StringSubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { + return GetAtomic(m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -107,7 +121,9 @@ class StringSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + return ::nt::GetAtomicString(m_subHandle, defaultValue); + } /** * Get the last published value along with its timestamp. @@ -118,7 +134,9 @@ class StringSubscriber : public Subscriber { * @return timestamped value */ TimestampedValueViewType GetAtomic( - wpi::SmallVectorImpl& buf) const; + wpi::SmallVectorImpl& buf) const { + return GetAtomic(buf, m_defaultValue); + } /** * Get the last published value along with its timestamp. @@ -131,7 +149,9 @@ class StringSubscriber : public Subscriber { */ TimestampedValueViewType GetAtomic( wpi::SmallVectorImpl& buf, - ParamType defaultValue) const; + ParamType defaultValue) const { + return nt::GetAtomicString(m_subHandle, buf, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -143,7 +163,9 @@ class StringSubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueString(m_subHandle); + } /** * Get the corresponding topic. @@ -178,7 +200,7 @@ class StringPublisher : public Publisher { * * @param handle Native handle */ - explicit StringPublisher(NT_Publisher handle); + explicit StringPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -186,7 +208,9 @@ class StringPublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetString(m_pubHandle, value, time); + } /** * Publish a default value. @@ -195,7 +219,9 @@ class StringPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultString(m_pubHandle, value); + } /** * Get the corresponding topic. @@ -233,7 +259,9 @@ class StringEntry final : public StringSubscriber, * @param handle Native handle * @param defaultValue Default value */ - StringEntry(NT_Entry handle, ParamType defaultValue); + StringEntry(NT_Entry handle, ParamType defaultValue) + : StringSubscriber{handle, defaultValue}, + StringPublisher{handle} {} /** * Determines if the native handle is valid. @@ -259,7 +287,9 @@ class StringEntry final : public StringSubscriber, /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { + ::nt::Unpublish(m_pubHandle); + } }; /** @@ -311,7 +341,11 @@ class StringTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return StringSubscriber{ + ::nt::Subscribe(m_handle, NT_STRING, "string", options), + defaultValue}; + } /** * Create a new subscriber to the topic, with specific type string. * @@ -331,7 +365,11 @@ class StringTopic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return StringSubscriber{ + ::nt::Subscribe(m_handle, NT_STRING, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. @@ -349,7 +387,10 @@ class StringTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return StringPublisher{ + ::nt::Publish(m_handle, NT_STRING, "string", options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -371,7 +412,10 @@ class StringTopic final : public Topic { */ [[nodiscard]] PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions); + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { + return StringPublisher{ + ::nt::PublishEx(m_handle, NT_STRING, typeString, properties, options)}; + } /** * Create a new entry for the topic. @@ -395,7 +439,11 @@ class StringTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return StringEntry{ + ::nt::GetEntry(m_handle, NT_STRING, "string", options), + defaultValue}; + } /** * Create a new entry for the topic, with specific type string. * @@ -419,10 +467,24 @@ class StringTopic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return StringEntry{ + ::nt::GetEntry(m_handle, NT_STRING, typeString, options), + defaultValue}; + } }; -} // namespace nt +inline StringTopic StringSubscriber::GetTopic() const { + return StringTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +inline StringTopic StringPublisher::GetTopic() const { + return StringTopic{::nt::GetTopicFromHandle(m_pubHandle)}; +} -#include "networktables/StringTopic.inc" +inline StringTopic StringEntry::GetTopic() const { + return StringTopic{::nt::GetTopicFromHandle(m_subHandle)}; +} + +} // namespace nt diff --git a/ntcore/src/generated/main/native/include/networktables/StringTopic.inc b/ntcore/src/generated/main/native/include/networktables/StringTopic.inc deleted file mode 100644 index 39428852af7..00000000000 --- a/ntcore/src/generated/main/native/include/networktables/StringTopic.inc +++ /dev/null @@ -1,137 +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. - -// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY - -#pragma once - -#include - -#include "networktables/StringTopic.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline StringSubscriber::StringSubscriber( - NT_Subscriber handle, ParamType defaultValue) - : Subscriber{handle}, - m_defaultValue{defaultValue} {} - -inline std::string StringSubscriber::Get() const { - return Get(m_defaultValue); -} - -inline std::string StringSubscriber::Get( - ParamType defaultValue) const { - return ::nt::GetString(m_subHandle, defaultValue); -} - -inline std::string_view StringSubscriber::Get(wpi::SmallVectorImpl& buf) const { - return Get(buf, m_defaultValue); -} - -inline std::string_view StringSubscriber::Get(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetString(m_subHandle, buf, defaultValue); -} - -inline TimestampedString StringSubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -inline TimestampedString StringSubscriber::GetAtomic( - ParamType defaultValue) const { - return ::nt::GetAtomicString(m_subHandle, defaultValue); -} - -inline TimestampedStringView StringSubscriber::GetAtomic(wpi::SmallVectorImpl& buf) const { - return GetAtomic(buf, m_defaultValue); -} - -inline TimestampedStringView StringSubscriber::GetAtomic(wpi::SmallVectorImpl& buf, ParamType defaultValue) const { - return nt::GetAtomicString(m_subHandle, buf, defaultValue); -} - -inline std::vector -StringSubscriber::ReadQueue() { - return ::nt::ReadQueueString(m_subHandle); -} - -inline StringTopic StringSubscriber::GetTopic() const { - return StringTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline StringPublisher::StringPublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void StringPublisher::Set(ParamType value, - int64_t time) { - ::nt::SetString(m_pubHandle, value, time); -} - -inline void StringPublisher::SetDefault(ParamType value) { - ::nt::SetDefaultString(m_pubHandle, value); -} - -inline StringTopic StringPublisher::GetTopic() const { - return StringTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline StringEntry::StringEntry( - NT_Entry handle, ParamType defaultValue) - : StringSubscriber{handle, defaultValue}, - StringPublisher{handle} {} - -inline StringTopic StringEntry::GetTopic() const { - return StringTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void StringEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} - -inline StringSubscriber StringTopic::Subscribe( - std::string_view defaultValue, - const PubSubOptions& options) { - return StringSubscriber{ - ::nt::Subscribe(m_handle, NT_STRING, "string", options), - defaultValue}; -} -inline StringSubscriber StringTopic::SubscribeEx( - std::string_view typeString, std::string_view defaultValue, - const PubSubOptions& options) { - return StringSubscriber{ - ::nt::Subscribe(m_handle, NT_STRING, typeString, options), - defaultValue}; -} - -inline StringPublisher StringTopic::Publish( - const PubSubOptions& options) { - return StringPublisher{ - ::nt::Publish(m_handle, NT_STRING, "string", options)}; -} - -inline StringPublisher StringTopic::PublishEx( - std::string_view typeString, - const wpi::json& properties, const PubSubOptions& options) { - return StringPublisher{ - ::nt::PublishEx(m_handle, NT_STRING, typeString, properties, options)}; -} - -inline StringEntry StringTopic::GetEntry( - std::string_view defaultValue, - const PubSubOptions& options) { - return StringEntry{ - ::nt::GetEntry(m_handle, NT_STRING, "string", options), - defaultValue}; -} -inline StringEntry StringTopic::GetEntryEx( - std::string_view typeString, std::string_view defaultValue, - const PubSubOptions& options) { - return StringEntry{ - ::nt::GetEntry(m_handle, NT_STRING, typeString, options), - defaultValue}; -} - -} // namespace nt diff --git a/ntcore/src/main/native/cpp/net/ClientMessageQueue.h b/ntcore/src/main/native/cpp/net/ClientMessageQueue.h index c2e6f950a8a..b4baeef2330 100644 --- a/ntcore/src/main/native/cpp/net/ClientMessageQueue.h +++ b/ntcore/src/main/native/cpp/net/ClientMessageQueue.h @@ -8,6 +8,7 @@ #include #include +#include #include #include "Message.h" @@ -40,20 +41,81 @@ class ClientMessageQueueImpl final : public ClientMessageHandler, bool empty() const { return m_queue.empty(); } // ClientMessageQueue - calls to these read the queue - std::span ReadQueue(std::span out) final; - void ClearQueue() final; + std::span ReadQueue(std::span out) final { + std::scoped_lock lock{m_mutex}; + size_t count = 0; + for (auto&& msg : out) { + if (!m_queue.try_dequeue(msg)) { + break; + } + if constexpr (MaxValueSize != 0) { + if (auto* val = std::get_if(&msg.contents)) { + m_valueSize.size -= sizeof(ClientMessage) + val->value.size(); + m_valueSize.errored = false; + } + } + ++count; + } + return out.subspan(0, count); + } + + void ClearQueue() final { + std::scoped_lock lock{m_mutex}; + ClientMessage msg; + while (m_queue.try_dequeue(msg)) { + } + if constexpr (MaxValueSize != 0) { + m_valueSize.size = 0; + m_valueSize.errored = false; + } + } // ClientMessageHandler - calls to these append to the queue void ClientPublish(int pubuid, std::string_view name, std::string_view typeStr, const wpi::json& properties, - const PubSubOptionsImpl& options) final; - void ClientUnpublish(int pubuid) final; + const PubSubOptionsImpl& options) final { + std::scoped_lock lock{m_mutex}; + m_queue.enqueue(ClientMessage{PublishMsg{ + pubuid, std::string{name}, std::string{typeStr}, properties, options}}); + } + + void ClientUnpublish(int pubuid) final { + std::scoped_lock lock{m_mutex}; + m_queue.enqueue(ClientMessage{UnpublishMsg{pubuid}}); + } + void ClientSetProperties(std::string_view name, - const wpi::json& update) final; + const wpi::json& update) final { + std::scoped_lock lock{m_mutex}; + m_queue.enqueue(ClientMessage{SetPropertiesMsg{std::string{name}, update}}); + } + void ClientSubscribe(int subuid, std::span topicNames, - const PubSubOptionsImpl& options) final; - void ClientUnsubscribe(int subuid) final; - void ClientSetValue(int pubuid, const Value& value) final; + const PubSubOptionsImpl& options) final { + std::scoped_lock lock{m_mutex}; + m_queue.enqueue(ClientMessage{ + SubscribeMsg{subuid, {topicNames.begin(), topicNames.end()}, options}}); + } + + void ClientUnsubscribe(int subuid) final { + std::scoped_lock lock{m_mutex}; + m_queue.enqueue(ClientMessage{UnsubscribeMsg{subuid}}); + } + + void ClientSetValue(int pubuid, const Value& value) final { + std::scoped_lock lock{m_mutex}; + if constexpr (MaxValueSize != 0) { + m_valueSize.size += sizeof(ClientMessage) + value.size(); + if (m_valueSize.size > MaxValueSize) { + if (!m_valueSize.errored) { + WPI_ERROR(m_logger, "NT: dropping value set due to memory limits"); + m_valueSize.errored = true; + } + return; // avoid potential out of memory + } + } + m_queue.enqueue(ClientMessage{ClientValueMsg{pubuid, value}}); + } private: wpi::FastQueue m_queue{kBlockSize - 1}; @@ -83,5 +145,3 @@ using LocalClientMessageQueue = using NetworkIncomingClientQueue = detail::ClientMessageQueueImpl<0, false>; } // namespace nt::net - -#include "ClientMessageQueue.inc" diff --git a/ntcore/src/main/native/cpp/net/ClientMessageQueue.inc b/ntcore/src/main/native/cpp/net/ClientMessageQueue.inc deleted file mode 100644 index fd2c5f13a76..00000000000 --- a/ntcore/src/main/native/cpp/net/ClientMessageQueue.inc +++ /dev/null @@ -1,106 +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 -#include - -#include - -#include "ClientMessageQueue.h" - -namespace nt::net::detail { - -template -inline void ClientMessageQueueImpl::ClientPublish( - int pubuid, std::string_view name, std::string_view typeStr, - const wpi::json& properties, const PubSubOptionsImpl& options) { - std::scoped_lock lock{m_mutex}; - m_queue.enqueue(ClientMessage{PublishMsg{ - pubuid, std::string{name}, std::string{typeStr}, properties, options}}); -} - -template -inline void ClientMessageQueueImpl::ClientUnpublish( - int pubuid) { - std::scoped_lock lock{m_mutex}; - m_queue.enqueue(ClientMessage{UnpublishMsg{pubuid}}); -} - -template -inline void -ClientMessageQueueImpl::ClientSetProperties( - std::string_view name, const wpi::json& update) { - std::scoped_lock lock{m_mutex}; - m_queue.enqueue(ClientMessage{SetPropertiesMsg{std::string{name}, update}}); -} - -template -inline void ClientMessageQueueImpl::ClientSubscribe( - int subuid, std::span topicNames, - const PubSubOptionsImpl& options) { - std::scoped_lock lock{m_mutex}; - m_queue.enqueue(ClientMessage{ - SubscribeMsg{subuid, {topicNames.begin(), topicNames.end()}, options}}); -} - -template -inline void ClientMessageQueueImpl::ClientUnsubscribe( - int subuid) { - std::scoped_lock lock{m_mutex}; - m_queue.enqueue(ClientMessage{UnsubscribeMsg{subuid}}); -} - -template -std::span -ClientMessageQueueImpl::ReadQueue( - std::span out) { - std::scoped_lock lock{m_mutex}; - size_t count = 0; - for (auto&& msg : out) { - if (!m_queue.try_dequeue(msg)) { - break; - } - if constexpr (MaxValueSize != 0) { - if (auto* val = std::get_if(&msg.contents)) { - m_valueSize.size -= sizeof(ClientMessage) + val->value.size(); - m_valueSize.errored = false; - } - } - ++count; - } - return out.subspan(0, count); -} - -template -void ClientMessageQueueImpl::ClearQueue() { - std::scoped_lock lock{m_mutex}; - ClientMessage msg; - while (m_queue.try_dequeue(msg)) { - } - if constexpr (MaxValueSize != 0) { - m_valueSize.size = 0; - m_valueSize.errored = false; - } -} - -template -void ClientMessageQueueImpl::ClientSetValue( - int pubuid, const Value& value) { - std::scoped_lock lock{m_mutex}; - if constexpr (MaxValueSize != 0) { - m_valueSize.size += sizeof(ClientMessage) + value.size(); - if (m_valueSize.size > MaxValueSize) { - if (!m_valueSize.errored) { - WPI_ERROR(m_logger, "NT: dropping value set due to memory limits"); - m_valueSize.errored = true; - } - return; // avoid potential out of memory - } - } - m_queue.enqueue(ClientMessage{ClientValueMsg{pubuid, value}}); -} - -} // namespace nt::net::detail diff --git a/ntcore/src/main/native/cpp/net/WebSocketConnection.h b/ntcore/src/main/native/cpp/net/WebSocketConnection.h index 68102949e54..4d494ae0566 100644 --- a/ntcore/src/main/native/cpp/net/WebSocketConnection.h +++ b/ntcore/src/main/native/cpp/net/WebSocketConnection.h @@ -59,8 +59,18 @@ class WebSocketConnection final return m_ws.GetLastReceivedTime(); } - void StopRead() final { m_ws.GetStream().StopRead(); } - void StartRead() final { m_ws.GetStream().StartRead(); } + void StopRead() final { + if (m_readActive) { + m_ws.GetStream().StopRead(); + m_readActive = false; + } + } + void StartRead() final { + if (!m_readActive) { + m_ws.GetStream().StartRead(); + m_readActive = true; + } + } void Disconnect(std::string_view reason) final; @@ -80,6 +90,7 @@ class WebSocketConnection final wpi::WebSocket& m_ws; wpi::Logger& m_logger; + bool m_readActive = true; class Stream; diff --git a/ntcore/src/main/native/cpp/net3/UvStreamConnection3.h b/ntcore/src/main/native/cpp/net3/UvStreamConnection3.h index a27e04ada20..6cb81eea002 100644 --- a/ntcore/src/main/native/cpp/net3/UvStreamConnection3.h +++ b/ntcore/src/main/native/cpp/net3/UvStreamConnection3.h @@ -41,8 +41,18 @@ class UvStreamConnection3 final uint64_t GetLastFlushTime() const final { return m_lastFlushTime; } - void StopRead() final { m_stream.StopRead(); } - void StartRead() final { m_stream.StartRead(); } + void StopRead() final { + if (m_readActive) { + m_stream.StopRead(); + m_readActive = false; + } + } + void StartRead() final { + if (!m_readActive) { + m_stream.StartRead(); + m_readActive = true; + } + } void Disconnect(std::string_view reason) final; @@ -62,6 +72,7 @@ class UvStreamConnection3 final std::string m_reason; uint64_t m_lastFlushTime = 0; int m_sendsActive = 0; + bool m_readActive = true; }; } // namespace nt::net3 diff --git a/ntcore/src/main/native/cpp/networktables/Topic.cpp b/ntcore/src/main/native/cpp/networktables/Topic.cpp index 1188667acd2..4447903df98 100644 --- a/ntcore/src/main/native/cpp/networktables/Topic.cpp +++ b/ntcore/src/main/native/cpp/networktables/Topic.cpp @@ -60,3 +60,7 @@ GenericEntry Topic::GetGenericEntry(std::string_view typeString, return GenericEntry{::nt::GetEntry( m_handle, ::nt::GetTypeFromString(typeString), typeString, options)}; } + +void Publisher::anchor() {} + +void Subscriber::anchor() {} diff --git a/ntcore/src/main/native/cpp/ntcore_c.cpp b/ntcore/src/main/native/cpp/ntcore_c.cpp index 83227928118..a31b404e050 100644 --- a/ntcore/src/main/native/cpp/ntcore_c.cpp +++ b/ntcore/src/main/native/cpp/ntcore_c.cpp @@ -407,6 +407,21 @@ NT_Topic NT_GetTopicFromHandle(NT_Handle pubsubentry) { return nt::GetTopicFromHandle(pubsubentry); } +NT_MultiSubscriber NT_SubscribeMultiple( + NT_Inst inst, const struct WPI_String* prefixes, size_t prefixes_len, + const struct NT_PubSubOptions* options) { + wpi::SmallVector p; + p.resize_for_overwrite(prefixes_len); + for (size_t i = 0; i < prefixes_len; ++i) { + p[i] = wpi::to_string_view(&prefixes[i]); + } + return nt::SubscribeMultiple(inst, p, ConvertToCpp(options)); +} + +void NT_UnsubscribeMultiple(NT_MultiSubscriber sub) { + nt::UnsubscribeMultiple(sub); +} + /* * Callback Creation Functions */ diff --git a/ntcore/src/main/native/include/networktables/GenericEntry.h b/ntcore/src/main/native/include/networktables/GenericEntry.h index 6c7fee4fe82..e71a25afad7 100644 --- a/ntcore/src/main/native/include/networktables/GenericEntry.h +++ b/ntcore/src/main/native/include/networktables/GenericEntry.h @@ -9,10 +9,10 @@ #include #include #include -#include #include #include "networktables/Topic.h" +#include "ntcore_cpp.h" namespace nt { @@ -36,7 +36,7 @@ class GenericSubscriber : public Subscriber { * * @param handle Native handle */ - explicit GenericSubscriber(NT_Subscriber handle); + explicit GenericSubscriber(NT_Subscriber handle) : Subscriber{handle} {} /** * Get the last published value. @@ -44,7 +44,7 @@ class GenericSubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { return ::nt::GetEntryValue(m_subHandle); } /** * Gets the entry's value as a boolean. If the entry does not exist or is of @@ -53,7 +53,9 @@ class GenericSubscriber : public Subscriber { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - bool GetBoolean(bool defaultValue) const; + bool GetBoolean(bool defaultValue) const { + return ::nt::GetBoolean(m_subHandle, defaultValue); + } /** * Gets the entry's value as a integer. If the entry does not exist or is of @@ -62,7 +64,9 @@ class GenericSubscriber : public Subscriber { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - int64_t GetInteger(int64_t defaultValue) const; + int64_t GetInteger(int64_t defaultValue) const { + return ::nt::GetInteger(m_subHandle, defaultValue); + } /** * Gets the entry's value as a float. If the entry does not exist or is of @@ -71,7 +75,9 @@ class GenericSubscriber : public Subscriber { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - float GetFloat(float defaultValue) const; + float GetFloat(float defaultValue) const { + return ::nt::GetFloat(m_subHandle, defaultValue); + } /** * Gets the entry's value as a double. If the entry does not exist or is of @@ -80,7 +86,9 @@ class GenericSubscriber : public Subscriber { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - double GetDouble(double defaultValue) const; + double GetDouble(double defaultValue) const { + return ::nt::GetDouble(m_subHandle, defaultValue); + } /** * Gets the entry's value as a string. If the entry does not exist or is of @@ -89,7 +97,9 @@ class GenericSubscriber : public Subscriber { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - std::string GetString(std::string_view defaultValue) const; + std::string GetString(std::string_view defaultValue) const { + return ::nt::GetString(m_subHandle, defaultValue); + } /** * Gets the entry's value as a raw. If the entry does not exist or is of @@ -98,7 +108,9 @@ class GenericSubscriber : public Subscriber { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - std::vector GetRaw(std::span defaultValue) const; + std::vector GetRaw(std::span defaultValue) const { + return ::nt::GetRaw(m_subHandle, defaultValue); + } /** * Gets the entry's value as a boolean array. If the entry does not exist @@ -114,7 +126,9 @@ class GenericSubscriber : public Subscriber { * because std::vector is special-cased in C++. 0 is false, any * non-zero value is true. */ - std::vector GetBooleanArray(std::span defaultValue) const; + std::vector GetBooleanArray(std::span defaultValue) const { + return ::nt::GetBooleanArray(m_subHandle, defaultValue); + } /** * Gets the entry's value as a integer array. If the entry does not exist @@ -127,7 +141,9 @@ class GenericSubscriber : public Subscriber { * concern, use GetValue() instead. */ std::vector GetIntegerArray( - std::span defaultValue) const; + std::span defaultValue) const { + return ::nt::GetIntegerArray(m_subHandle, defaultValue); + } /** * Gets the entry's value as a float array. If the entry does not exist @@ -139,7 +155,9 @@ class GenericSubscriber : public Subscriber { * @note This makes a copy of the array. If the overhead of this is a * concern, use GetValue() instead. */ - std::vector GetFloatArray(std::span defaultValue) const; + std::vector GetFloatArray(std::span defaultValue) const { + return ::nt::GetFloatArray(m_subHandle, defaultValue); + } /** * Gets the entry's value as a double array. If the entry does not exist @@ -152,7 +170,9 @@ class GenericSubscriber : public Subscriber { * concern, use GetValue() instead. */ std::vector GetDoubleArray( - std::span defaultValue) const; + std::span defaultValue) const { + return ::nt::GetDoubleArray(m_subHandle, defaultValue); + } /** * Gets the entry's value as a string array. If the entry does not exist @@ -165,7 +185,9 @@ class GenericSubscriber : public Subscriber { * concern, use GetValue() instead. */ std::vector GetStringArray( - std::span defaultValue) const; + std::span defaultValue) const { + return ::nt::GetStringArray(m_subHandle, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -177,14 +199,18 @@ class GenericSubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return ::nt::ReadQueueValue(m_subHandle); + } /** * Get the corresponding topic. * * @return Topic */ - TopicType GetTopic() const; + TopicType GetTopic() const { + return Topic{::nt::GetTopicFromHandle(m_subHandle)}; + } }; /** @@ -205,14 +231,14 @@ class GenericPublisher : public Publisher { * * @param handle Native handle */ - explicit GenericPublisher(NT_Publisher handle); + explicit GenericPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. * * @param value value to publish */ - void Set(ParamType value); + void Set(ParamType value) { ::nt::SetEntryValue(m_pubHandle, value); } /** * Sets the entry's value. @@ -221,7 +247,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetBoolean(bool value, int64_t time = 0); + bool SetBoolean(bool value, int64_t time = 0) { + return nt::SetBoolean(m_pubHandle, value, time); + } /** * Sets the entry's value. @@ -230,7 +258,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetInteger(int64_t value, int64_t time = 0); + bool SetInteger(int64_t value, int64_t time = 0) { + return nt::SetInteger(m_pubHandle, value, time); + } /** * Sets the entry's value. @@ -239,7 +269,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetFloat(float value, int64_t time = 0); + bool SetFloat(float value, int64_t time = 0) { + return nt::SetFloat(m_pubHandle, value, time); + } /** * Sets the entry's value. @@ -248,7 +280,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetDouble(double value, int64_t time = 0); + bool SetDouble(double value, int64_t time = 0) { + return nt::SetDouble(m_pubHandle, value, time); + } /** * Sets the entry's value. @@ -257,7 +291,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetString(std::string_view value, int64_t time = 0); + bool SetString(std::string_view value, int64_t time = 0) { + return nt::SetString(m_pubHandle, value, time); + } /** * Sets the entry's value. @@ -266,7 +302,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetRaw(std::span value, int64_t time = 0); + bool SetRaw(std::span value, int64_t time = 0) { + return nt::SetRaw(m_pubHandle, value, time); + } /** * Sets the entry's value. @@ -275,7 +313,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetBooleanArray(std::span value, int64_t time = 0); + bool SetBooleanArray(std::span value, int64_t time = 0) { + return SetEntryValue(m_pubHandle, Value::MakeBooleanArray(value, time)); + } /** * Sets the entry's value. @@ -284,7 +324,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetBooleanArray(std::span value, int64_t time = 0); + bool SetBooleanArray(std::span value, int64_t time = 0) { + return nt::SetBooleanArray(m_pubHandle, value, time); + } /** * Sets the entry's value. @@ -293,7 +335,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetIntegerArray(std::span value, int64_t time = 0); + bool SetIntegerArray(std::span value, int64_t time = 0) { + return nt::SetIntegerArray(m_pubHandle, value, time); + } /** * Sets the entry's value. @@ -302,7 +346,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetFloatArray(std::span value, int64_t time = 0); + bool SetFloatArray(std::span value, int64_t time = 0) { + return nt::SetFloatArray(m_pubHandle, value, time); + } /** * Sets the entry's value. @@ -311,7 +357,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetDoubleArray(std::span value, int64_t time = 0); + bool SetDoubleArray(std::span value, int64_t time = 0) { + return nt::SetDoubleArray(m_pubHandle, value, time); + } /** * Sets the entry's value. @@ -320,7 +368,9 @@ class GenericPublisher : public Publisher { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetStringArray(std::span value, int64_t time = 0); + bool SetStringArray(std::span value, int64_t time = 0) { + return nt::SetStringArray(m_pubHandle, value, time); + } /** * Publish a default value. @@ -329,7 +379,9 @@ class GenericPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultEntryValue(m_pubHandle, value); + } /** * Sets the entry's value if it does not exist. @@ -337,7 +389,9 @@ class GenericPublisher : public Publisher { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultBoolean(bool defaultValue); + bool SetDefaultBoolean(bool defaultValue) { + return nt::SetDefaultBoolean(m_pubHandle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -345,7 +399,9 @@ class GenericPublisher : public Publisher { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultInteger(int64_t defaultValue); + bool SetDefaultInteger(int64_t defaultValue) { + return nt::SetDefaultInteger(m_pubHandle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -353,7 +409,9 @@ class GenericPublisher : public Publisher { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultFloat(float defaultValue); + bool SetDefaultFloat(float defaultValue) { + return nt::SetDefaultFloat(m_pubHandle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -361,7 +419,9 @@ class GenericPublisher : public Publisher { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultDouble(double defaultValue); + bool SetDefaultDouble(double defaultValue) { + return nt::SetDefaultDouble(m_pubHandle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -369,7 +429,9 @@ class GenericPublisher : public Publisher { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultString(std::string_view defaultValue); + bool SetDefaultString(std::string_view defaultValue) { + return nt::SetDefaultString(m_pubHandle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -377,7 +439,9 @@ class GenericPublisher : public Publisher { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultRaw(std::span defaultValue); + bool SetDefaultRaw(std::span defaultValue) { + return nt::SetDefaultRaw(m_pubHandle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -385,7 +449,9 @@ class GenericPublisher : public Publisher { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultBooleanArray(std::span defaultValue); + bool SetDefaultBooleanArray(std::span defaultValue) { + return nt::SetDefaultBooleanArray(m_pubHandle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -393,7 +459,9 @@ class GenericPublisher : public Publisher { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultIntegerArray(std::span defaultValue); + bool SetDefaultIntegerArray(std::span defaultValue) { + return nt::SetDefaultIntegerArray(m_pubHandle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -401,7 +469,9 @@ class GenericPublisher : public Publisher { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultFloatArray(std::span defaultValue); + bool SetDefaultFloatArray(std::span defaultValue) { + return nt::SetDefaultFloatArray(m_pubHandle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -409,7 +479,9 @@ class GenericPublisher : public Publisher { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultDoubleArray(std::span defaultValue); + bool SetDefaultDoubleArray(std::span defaultValue) { + return nt::SetDefaultDoubleArray(m_pubHandle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -417,14 +489,18 @@ class GenericPublisher : public Publisher { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultStringArray(std::span defaultValue); + bool SetDefaultStringArray(std::span defaultValue) { + return nt::SetDefaultStringArray(m_pubHandle, defaultValue); + } /** * Get the corresponding topic. * * @return Topic */ - TopicType GetTopic() const; + TopicType GetTopic() const { + return Topic{::nt::GetTopicFromHandle(m_pubHandle)}; + } }; /** @@ -449,7 +525,8 @@ class GenericEntry final : public GenericSubscriber, public GenericPublisher { * * @param handle Native handle */ - explicit GenericEntry(NT_Entry handle); + explicit GenericEntry(NT_Entry handle) + : GenericSubscriber{handle}, GenericPublisher{handle} {} /** * Determines if the native handle is valid. @@ -470,14 +547,14 @@ class GenericEntry final : public GenericSubscriber, public GenericPublisher { * * @return Topic */ - TopicType GetTopic() const; + TopicType GetTopic() const { + return Topic{::nt::GetTopicFromHandle(m_subHandle)}; + } /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { ::nt::Unpublish(m_pubHandle); } }; } // namespace nt - -#include "networktables/GenericEntry.inc" diff --git a/ntcore/src/main/native/include/networktables/GenericEntry.inc b/ntcore/src/main/native/include/networktables/GenericEntry.inc deleted file mode 100644 index f3d996707bc..00000000000 --- a/ntcore/src/main/native/include/networktables/GenericEntry.inc +++ /dev/null @@ -1,214 +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 -#include -#include -#include - -#include "networktables/GenericEntry.h" -#include "networktables/NetworkTableType.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline GenericSubscriber::GenericSubscriber(NT_Subscriber handle) - : Subscriber{handle} {} - -inline Value GenericSubscriber::Get() const { - return ::nt::GetEntryValue(m_subHandle); -} - -inline bool GenericSubscriber::GetBoolean(bool defaultValue) const { - return ::nt::GetBoolean(m_subHandle, defaultValue); -} - -inline int64_t GenericSubscriber::GetInteger(int64_t defaultValue) const { - return ::nt::GetInteger(m_subHandle, defaultValue); -} - -inline float GenericSubscriber::GetFloat(float defaultValue) const { - return ::nt::GetFloat(m_subHandle, defaultValue); -} - -inline double GenericSubscriber::GetDouble(double defaultValue) const { - return ::nt::GetDouble(m_subHandle, defaultValue); -} - -inline std::string GenericSubscriber::GetString( - std::string_view defaultValue) const { - return ::nt::GetString(m_subHandle, defaultValue); -} - -inline std::vector GenericSubscriber::GetRaw( - std::span defaultValue) const { - return ::nt::GetRaw(m_subHandle, defaultValue); -} - -inline std::vector GenericSubscriber::GetBooleanArray( - std::span defaultValue) const { - return ::nt::GetBooleanArray(m_subHandle, defaultValue); -} - -inline std::vector GenericSubscriber::GetIntegerArray( - std::span defaultValue) const { - return ::nt::GetIntegerArray(m_subHandle, defaultValue); -} - -inline std::vector GenericSubscriber::GetFloatArray( - std::span defaultValue) const { - return ::nt::GetFloatArray(m_subHandle, defaultValue); -} - -inline std::vector GenericSubscriber::GetDoubleArray( - std::span defaultValue) const { - return ::nt::GetDoubleArray(m_subHandle, defaultValue); -} - -inline std::vector GenericSubscriber::GetStringArray( - std::span defaultValue) const { - return ::nt::GetStringArray(m_subHandle, defaultValue); -} - -inline std::vector GenericSubscriber::ReadQueue() { - return ::nt::ReadQueueValue(m_subHandle); -} - -inline Topic GenericSubscriber::GetTopic() const { - return Topic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline GenericPublisher::GenericPublisher(NT_Publisher handle) - : Publisher{handle} {} - -inline void GenericPublisher::Set(const Value& value) { - ::nt::SetEntryValue(m_pubHandle, value); -} - -inline bool GenericPublisher::SetBoolean(bool value, int64_t time) { - return nt::SetBoolean(m_pubHandle, value, time); -} - -inline bool GenericPublisher::SetInteger(int64_t value, int64_t time) { - return nt::SetInteger(m_pubHandle, value, time); -} - -inline bool GenericPublisher::SetFloat(float value, int64_t time) { - return nt::SetFloat(m_pubHandle, value, time); -} - -inline bool GenericPublisher::SetDouble(double value, int64_t time) { - return nt::SetDouble(m_pubHandle, value, time); -} - -inline bool GenericPublisher::SetString(std::string_view value, int64_t time) { - return nt::SetString(m_pubHandle, value, time); -} - -inline bool GenericPublisher::SetRaw(std::span value, - int64_t time) { - return nt::SetRaw(m_pubHandle, value, time); -} - -inline bool GenericPublisher::SetBooleanArray(std::span value, - int64_t time) { - return SetEntryValue(m_pubHandle, Value::MakeBooleanArray(value, time)); -} - -inline bool GenericPublisher::SetBooleanArray(std::span value, - int64_t time) { - return nt::SetBooleanArray(m_pubHandle, value, time); -} - -inline bool GenericPublisher::SetIntegerArray(std::span value, - int64_t time) { - return nt::SetIntegerArray(m_pubHandle, value, time); -} - -inline bool GenericPublisher::SetFloatArray(std::span value, - int64_t time) { - return nt::SetFloatArray(m_pubHandle, value, time); -} - -inline bool GenericPublisher::SetDoubleArray(std::span value, - int64_t time) { - return nt::SetDoubleArray(m_pubHandle, value, time); -} - -inline bool GenericPublisher::SetStringArray(std::span value, - int64_t time) { - return nt::SetStringArray(m_pubHandle, value, time); -} - -inline void GenericPublisher::SetDefault(const Value& value) { - ::nt::SetDefaultEntryValue(m_pubHandle, value); -} - -inline bool GenericPublisher::SetDefaultBoolean(bool defaultValue) { - return nt::SetDefaultBoolean(m_pubHandle, defaultValue); -} - -inline bool GenericPublisher::SetDefaultInteger(int64_t defaultValue) { - return nt::SetDefaultInteger(m_pubHandle, defaultValue); -} - -inline bool GenericPublisher::SetDefaultFloat(float defaultValue) { - return nt::SetDefaultFloat(m_pubHandle, defaultValue); -} - -inline bool GenericPublisher::SetDefaultDouble(double defaultValue) { - return nt::SetDefaultDouble(m_pubHandle, defaultValue); -} - -inline bool GenericPublisher::SetDefaultString(std::string_view defaultValue) { - return nt::SetDefaultString(m_pubHandle, defaultValue); -} - -inline bool GenericPublisher::SetDefaultRaw( - std::span defaultValue) { - return nt::SetDefaultRaw(m_pubHandle, defaultValue); -} - -inline bool GenericPublisher::SetDefaultBooleanArray( - std::span defaultValue) { - return nt::SetDefaultBooleanArray(m_pubHandle, defaultValue); -} - -inline bool GenericPublisher::SetDefaultIntegerArray( - std::span defaultValue) { - return nt::SetDefaultIntegerArray(m_pubHandle, defaultValue); -} - -inline bool GenericPublisher::SetDefaultFloatArray( - std::span defaultValue) { - return nt::SetDefaultFloatArray(m_pubHandle, defaultValue); -} - -inline bool GenericPublisher::SetDefaultDoubleArray( - std::span defaultValue) { - return nt::SetDefaultDoubleArray(m_pubHandle, defaultValue); -} - -inline bool GenericPublisher::SetDefaultStringArray( - std::span defaultValue) { - return nt::SetDefaultStringArray(m_pubHandle, defaultValue); -} - -inline Topic GenericPublisher::GetTopic() const { - return Topic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -inline GenericEntry::GenericEntry(NT_Entry handle) - : GenericSubscriber{handle}, GenericPublisher{handle} {} - -inline Topic GenericEntry::GetTopic() const { - return Topic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline void GenericEntry::Unpublish() { - ::nt::Unpublish(m_pubHandle); -} -} // namespace nt diff --git a/ntcore/src/main/native/include/networktables/MultiSubscriber.h b/ntcore/src/main/native/include/networktables/MultiSubscriber.h index f146351b627..85afee58f0f 100644 --- a/ntcore/src/main/native/include/networktables/MultiSubscriber.h +++ b/ntcore/src/main/native/include/networktables/MultiSubscriber.h @@ -30,13 +30,31 @@ class MultiSubscriber final { */ MultiSubscriber(NetworkTableInstance inst, std::span prefixes, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) + : m_handle{::nt::SubscribeMultiple(inst.GetHandle(), prefixes, options)} { + } MultiSubscriber(const MultiSubscriber&) = delete; MultiSubscriber& operator=(const MultiSubscriber&) = delete; - MultiSubscriber(MultiSubscriber&& rhs); - MultiSubscriber& operator=(MultiSubscriber&& rhs); - ~MultiSubscriber(); + + MultiSubscriber(MultiSubscriber&& rhs) : m_handle{rhs.m_handle} { + rhs.m_handle = 0; + } + + MultiSubscriber& operator=(MultiSubscriber&& rhs) { + if (m_handle != 0) { + ::nt::UnsubscribeMultiple(m_handle); + } + m_handle = rhs.m_handle; + rhs.m_handle = 0; + return *this; + } + + ~MultiSubscriber() { + if (m_handle != 0) { + ::nt::UnsubscribeMultiple(m_handle); + } + } /** * Determines if the native handle is valid. @@ -57,5 +75,3 @@ class MultiSubscriber final { }; } // namespace nt - -#include "MultiSubscriber.inc" diff --git a/ntcore/src/main/native/include/networktables/MultiSubscriber.inc b/ntcore/src/main/native/include/networktables/MultiSubscriber.inc deleted file mode 100644 index c32c06a8785..00000000000 --- a/ntcore/src/main/native/include/networktables/MultiSubscriber.inc +++ /dev/null @@ -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 "networktables/MultiSubscriber.h" - -namespace nt { - -inline MultiSubscriber::MultiSubscriber( - NetworkTableInstance inst, std::span prefixes, - const PubSubOptions& options) - : m_handle{::nt::SubscribeMultiple(inst.GetHandle(), prefixes, options)} {} - -inline MultiSubscriber::MultiSubscriber(MultiSubscriber&& rhs) - : m_handle{rhs.m_handle} { - rhs.m_handle = 0; -} - -inline MultiSubscriber& MultiSubscriber::operator=(MultiSubscriber&& rhs) { - if (m_handle != 0) { - ::nt::UnsubscribeMultiple(m_handle); - } - m_handle = rhs.m_handle; - rhs.m_handle = 0; - return *this; -} - -inline MultiSubscriber::~MultiSubscriber() { - if (m_handle != 0) { - ::nt::UnsubscribeMultiple(m_handle); - } -} - -} // namespace nt diff --git a/ntcore/src/main/native/include/networktables/NetworkTableEntry.h b/ntcore/src/main/native/include/networktables/NetworkTableEntry.h index 6eec8964f36..6b4cd11a85c 100644 --- a/ntcore/src/main/native/include/networktables/NetworkTableEntry.h +++ b/ntcore/src/main/native/include/networktables/NetworkTableEntry.h @@ -6,8 +6,6 @@ #include -#include -#include #include #include #include @@ -15,7 +13,6 @@ #include "networktables/NetworkTableType.h" #include "networktables/NetworkTableValue.h" -#include "ntcore_c.h" #include "ntcore_cpp.h" namespace nt { @@ -36,14 +33,14 @@ class NetworkTableEntry final { /** * Construct invalid instance. */ - NetworkTableEntry(); + NetworkTableEntry() = default; /** * Construct from native handle. * * @param handle Native handle */ - explicit NetworkTableEntry(NT_Entry handle); + explicit NetworkTableEntry(NT_Entry handle) : m_handle{handle} {} /** * Determines if the native handle is valid. @@ -57,7 +54,7 @@ class NetworkTableEntry final { * * @return Native handle */ - NT_Entry GetHandle() const; + NT_Entry GetHandle() const { return m_handle; } /** * Gets the instance for the entry. @@ -71,28 +68,30 @@ class NetworkTableEntry final { * * @return True if the entry exists, false otherwise. */ - bool Exists() const; + bool Exists() const { return GetEntryType(m_handle) != NT_UNASSIGNED; } /** * Gets the name of the entry (the key). * * @return the entry's name */ - std::string GetName() const; + std::string GetName() const { return GetEntryName(m_handle); } /** * Gets the type of the entry. * * @return the entry's type */ - NetworkTableType GetType() const; + NetworkTableType GetType() const { + return static_cast(GetEntryType(m_handle)); + } /** * Gets the last time the entry's value was changed. * * @return Entry last change time */ - int64_t GetLastChange() const; + int64_t GetLastChange() const { return GetEntryLastChange(m_handle); } /** * Gets the entry's value. If the entry does not exist, returns an empty @@ -100,7 +99,7 @@ class NetworkTableEntry final { * * @return the entry's value or an empty value if it does not exist. */ - Value GetValue() const; + Value GetValue() const { return GetEntryValue(m_handle); } /** * Gets the entry's value as a boolean. If the entry does not exist or is of @@ -109,7 +108,9 @@ class NetworkTableEntry final { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - bool GetBoolean(bool defaultValue) const; + bool GetBoolean(bool defaultValue) const { + return nt::GetBoolean(m_handle, defaultValue); + } /** * Gets the entry's value as a integer. If the entry does not exist or is of @@ -118,7 +119,9 @@ class NetworkTableEntry final { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - int64_t GetInteger(int64_t defaultValue) const; + int64_t GetInteger(int64_t defaultValue) const { + return nt::GetInteger(m_handle, defaultValue); + } /** * Gets the entry's value as a float. If the entry does not exist or is of @@ -127,7 +130,9 @@ class NetworkTableEntry final { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - float GetFloat(float defaultValue) const; + float GetFloat(float defaultValue) const { + return nt::GetFloat(m_handle, defaultValue); + } /** * Gets the entry's value as a double. If the entry does not exist or is of @@ -136,7 +141,9 @@ class NetworkTableEntry final { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - double GetDouble(double defaultValue) const; + double GetDouble(double defaultValue) const { + return nt::GetDouble(m_handle, defaultValue); + } /** * Gets the entry's value as a string. If the entry does not exist or is of @@ -145,7 +152,9 @@ class NetworkTableEntry final { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - std::string GetString(std::string_view defaultValue) const; + std::string GetString(std::string_view defaultValue) const { + return nt::GetString(m_handle, defaultValue); + } /** * Gets the entry's value as a raw. If the entry does not exist or is of @@ -154,7 +163,9 @@ class NetworkTableEntry final { * @param defaultValue the value to be returned if no value is found * @return the entry's value or the given default value */ - std::vector GetRaw(std::span defaultValue) const; + std::vector GetRaw(std::span defaultValue) const { + return nt::GetRaw(m_handle, defaultValue); + } /** * Gets the entry's value as a boolean array. If the entry does not exist @@ -170,7 +181,9 @@ class NetworkTableEntry final { * because std::vector is special-cased in C++. 0 is false, any * non-zero value is true. */ - std::vector GetBooleanArray(std::span defaultValue) const; + std::vector GetBooleanArray(std::span defaultValue) const { + return nt::GetBooleanArray(m_handle, defaultValue); + } /** * Gets the entry's value as a integer array. If the entry does not exist @@ -183,7 +196,9 @@ class NetworkTableEntry final { * concern, use GetValue() instead. */ std::vector GetIntegerArray( - std::span defaultValue) const; + std::span defaultValue) const { + return nt::GetIntegerArray(m_handle, defaultValue); + } /** * Gets the entry's value as a float array. If the entry does not exist @@ -195,7 +210,9 @@ class NetworkTableEntry final { * @note This makes a copy of the array. If the overhead of this is a * concern, use GetValue() instead. */ - std::vector GetFloatArray(std::span defaultValue) const; + std::vector GetFloatArray(std::span defaultValue) const { + return nt::GetFloatArray(m_handle, defaultValue); + } /** * Gets the entry's value as a double array. If the entry does not exist @@ -208,7 +225,9 @@ class NetworkTableEntry final { * concern, use GetValue() instead. */ std::vector GetDoubleArray( - std::span defaultValue) const; + std::span defaultValue) const { + return nt::GetDoubleArray(m_handle, defaultValue); + } /** * Gets the entry's value as a string array. If the entry does not exist @@ -221,7 +240,9 @@ class NetworkTableEntry final { * concern, use GetValue() instead. */ std::vector GetStringArray( - std::span defaultValue) const; + std::span defaultValue) const { + return nt::GetStringArray(m_handle, defaultValue); + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -231,7 +252,9 @@ class NetworkTableEntry final { * @return Array of values; empty array if no new changes have been * published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + return nt::ReadQueueValue(m_handle); + } /** * Sets the entry's value if it does not exist. @@ -239,7 +262,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultValue(const Value& defaultValue); + bool SetDefaultValue(const Value& defaultValue) { + return SetDefaultEntryValue(m_handle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -247,7 +272,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultBoolean(bool defaultValue); + bool SetDefaultBoolean(bool defaultValue) { + return nt::SetDefaultBoolean(m_handle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -255,7 +282,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultInteger(int64_t defaultValue); + bool SetDefaultInteger(int64_t defaultValue) { + return nt::SetDefaultInteger(m_handle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -263,7 +292,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultFloat(float defaultValue); + bool SetDefaultFloat(float defaultValue) { + return nt::SetDefaultFloat(m_handle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -271,7 +302,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultDouble(double defaultValue); + bool SetDefaultDouble(double defaultValue) { + return nt::SetDefaultDouble(m_handle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -279,7 +312,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultString(std::string_view defaultValue); + bool SetDefaultString(std::string_view defaultValue) { + return nt::SetDefaultString(m_handle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -287,7 +322,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultRaw(std::span defaultValue); + bool SetDefaultRaw(std::span defaultValue) { + return nt::SetDefaultRaw(m_handle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -295,7 +332,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultBooleanArray(std::span defaultValue); + bool SetDefaultBooleanArray(std::span defaultValue) { + return nt::SetDefaultBooleanArray(m_handle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -303,7 +342,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultIntegerArray(std::span defaultValue); + bool SetDefaultIntegerArray(std::span defaultValue) { + return nt::SetDefaultIntegerArray(m_handle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -311,7 +352,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultFloatArray(std::span defaultValue); + bool SetDefaultFloatArray(std::span defaultValue) { + return nt::SetDefaultFloatArray(m_handle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -319,7 +362,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultDoubleArray(std::span defaultValue); + bool SetDefaultDoubleArray(std::span defaultValue) { + return nt::SetDefaultDoubleArray(m_handle, defaultValue); + } /** * Sets the entry's value if it does not exist. @@ -327,7 +372,9 @@ class NetworkTableEntry final { * @param defaultValue the default value to set * @return False if the entry exists with a different type */ - bool SetDefaultStringArray(std::span defaultValue); + bool SetDefaultStringArray(std::span defaultValue) { + return nt::SetDefaultStringArray(m_handle, defaultValue); + } /** * Sets the entry's value. @@ -335,7 +382,7 @@ class NetworkTableEntry final { * @param value the value to set * @return False if the entry exists with a different type */ - bool SetValue(const Value& value); + bool SetValue(const Value& value) { return SetEntryValue(m_handle, value); } /** * Sets the entry's value. @@ -344,7 +391,9 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetBoolean(bool value, int64_t time = 0); + bool SetBoolean(bool value, int64_t time = 0) { + return nt::SetBoolean(m_handle, value, time); + } /** * Sets the entry's value. @@ -353,7 +402,9 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetInteger(int64_t value, int64_t time = 0); + bool SetInteger(int64_t value, int64_t time = 0) { + return nt::SetInteger(m_handle, value, time); + } /** * Sets the entry's value. @@ -362,7 +413,9 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetFloat(float value, int64_t time = 0); + bool SetFloat(float value, int64_t time = 0) { + return nt::SetFloat(m_handle, value, time); + } /** * Sets the entry's value. @@ -371,7 +424,9 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetDouble(double value, int64_t time = 0); + bool SetDouble(double value, int64_t time = 0) { + return nt::SetDouble(m_handle, value, time); + } /** * Sets the entry's value. @@ -380,7 +435,9 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetString(std::string_view value, int64_t time = 0); + bool SetString(std::string_view value, int64_t time = 0) { + return nt::SetString(m_handle, value, time); + } /** * Sets the entry's value. @@ -389,7 +446,9 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetRaw(std::span value, int64_t time = 0); + bool SetRaw(std::span value, int64_t time = 0) { + return nt::SetRaw(m_handle, value, time); + } /** * Sets the entry's value. @@ -398,7 +457,9 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetBooleanArray(std::span value, int64_t time = 0); + bool SetBooleanArray(std::span value, int64_t time = 0) { + return SetEntryValue(m_handle, Value::MakeBooleanArray(value, time)); + } /** * Sets the entry's value. @@ -407,7 +468,9 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetBooleanArray(std::span value, int64_t time = 0); + bool SetBooleanArray(std::span value, int64_t time = 0) { + return nt::SetBooleanArray(m_handle, value, time); + } /** * Sets the entry's value. @@ -416,7 +479,9 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetIntegerArray(std::span value, int64_t time = 0); + bool SetIntegerArray(std::span value, int64_t time = 0) { + return nt::SetIntegerArray(m_handle, value, time); + } /** * Sets the entry's value. @@ -425,7 +490,9 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetFloatArray(std::span value, int64_t time = 0); + bool SetFloatArray(std::span value, int64_t time = 0) { + return nt::SetFloatArray(m_handle, value, time); + } /** * Sets the entry's value. @@ -434,7 +501,9 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetDoubleArray(std::span value, int64_t time = 0); + bool SetDoubleArray(std::span value, int64_t time = 0) { + return nt::SetDoubleArray(m_handle, value, time); + } /** * Sets the entry's value. @@ -443,29 +512,37 @@ class NetworkTableEntry final { * @param time the timestamp to set (0 = nt::Now()) * @return False if the entry exists with a different type */ - bool SetStringArray(std::span value, int64_t time = 0); + bool SetStringArray(std::span value, int64_t time = 0) { + return nt::SetStringArray(m_handle, value, time); + } /** * Make value persistent through program restarts. */ - void SetPersistent(); + void SetPersistent() { + nt::SetTopicPersistent(nt::GetTopicFromHandle(m_handle), true); + } /** * Stop making value persistent through program restarts. */ - void ClearPersistent(); + void ClearPersistent() { + nt::SetTopicPersistent(nt::GetTopicFromHandle(m_handle), false); + } /** * Returns whether the value is persistent through program restarts. * * @return True if the value is persistent. */ - bool IsPersistent() const; + bool IsPersistent() const { + return nt::GetTopicPersistent(nt::GetTopicFromHandle(m_handle)); + } /** * Stops publishing the entry if it's been published. */ - void Unpublish(); + void Unpublish() { return nt::Unpublish(m_handle); } /** * Gets the entry's topic. @@ -486,5 +563,3 @@ class NetworkTableEntry final { }; } // namespace nt - -#include "networktables/NetworkTableEntry.inc" diff --git a/ntcore/src/main/native/include/networktables/NetworkTableEntry.inc b/ntcore/src/main/native/include/networktables/NetworkTableEntry.inc deleted file mode 100644 index 0f18e2d445d..00000000000 --- a/ntcore/src/main/native/include/networktables/NetworkTableEntry.inc +++ /dev/null @@ -1,231 +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 -#include -#include -#include - -#include "networktables/NetworkTableEntry.h" -#include "ntcore_cpp.h" -#include "ntcore_cpp_types.h" - -namespace nt { - -inline NetworkTableEntry::NetworkTableEntry() {} - -inline NetworkTableEntry::NetworkTableEntry(NT_Entry handle) - : m_handle{handle} {} - -inline NT_Entry NetworkTableEntry::GetHandle() const { - return m_handle; -} - -inline bool NetworkTableEntry::Exists() const { - return GetEntryType(m_handle) != NT_UNASSIGNED; -} - -inline std::string NetworkTableEntry::GetName() const { - return GetEntryName(m_handle); -} - -inline NetworkTableType NetworkTableEntry::GetType() const { - return static_cast(GetEntryType(m_handle)); -} - -inline int64_t NetworkTableEntry::GetLastChange() const { - return GetEntryLastChange(m_handle); -} - -inline Value NetworkTableEntry::GetValue() const { - return GetEntryValue(m_handle); -} - -inline bool NetworkTableEntry::GetBoolean(bool defaultValue) const { - return nt::GetBoolean(m_handle, defaultValue); -} - -inline int64_t NetworkTableEntry::GetInteger(int64_t defaultValue) const { - return nt::GetInteger(m_handle, defaultValue); -} - -inline float NetworkTableEntry::GetFloat(float defaultValue) const { - return nt::GetFloat(m_handle, defaultValue); -} - -inline double NetworkTableEntry::GetDouble(double defaultValue) const { - return nt::GetDouble(m_handle, defaultValue); -} - -inline std::string NetworkTableEntry::GetString( - std::string_view defaultValue) const { - return nt::GetString(m_handle, defaultValue); -} - -inline std::vector NetworkTableEntry::GetRaw( - std::span defaultValue) const { - return nt::GetRaw(m_handle, defaultValue); -} - -inline std::vector NetworkTableEntry::GetBooleanArray( - std::span defaultValue) const { - return nt::GetBooleanArray(m_handle, defaultValue); -} - -inline std::vector NetworkTableEntry::GetIntegerArray( - std::span defaultValue) const { - return nt::GetIntegerArray(m_handle, defaultValue); -} - -inline std::vector NetworkTableEntry::GetFloatArray( - std::span defaultValue) const { - return nt::GetFloatArray(m_handle, defaultValue); -} - -inline std::vector NetworkTableEntry::GetDoubleArray( - std::span defaultValue) const { - return nt::GetDoubleArray(m_handle, defaultValue); -} - -inline std::vector NetworkTableEntry::GetStringArray( - std::span defaultValue) const { - return nt::GetStringArray(m_handle, defaultValue); -} - -inline std::vector NetworkTableEntry::ReadQueue() { - return nt::ReadQueueValue(m_handle); -} - -inline bool NetworkTableEntry::SetDefaultValue(const Value& defaultValue) { - return SetDefaultEntryValue(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetDefaultBoolean(bool defaultValue) { - return nt::SetDefaultBoolean(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetDefaultInteger(int64_t defaultValue) { - return nt::SetDefaultInteger(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetDefaultFloat(float defaultValue) { - return nt::SetDefaultFloat(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetDefaultDouble(double defaultValue) { - return nt::SetDefaultDouble(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetDefaultString(std::string_view defaultValue) { - return nt::SetDefaultString(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetDefaultRaw( - std::span defaultValue) { - return nt::SetDefaultRaw(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetDefaultBooleanArray( - std::span defaultValue) { - return nt::SetDefaultBooleanArray(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetDefaultIntegerArray( - std::span defaultValue) { - return nt::SetDefaultIntegerArray(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetDefaultFloatArray( - std::span defaultValue) { - return nt::SetDefaultFloatArray(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetDefaultDoubleArray( - std::span defaultValue) { - return nt::SetDefaultDoubleArray(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetDefaultStringArray( - std::span defaultValue) { - return nt::SetDefaultStringArray(m_handle, defaultValue); -} - -inline bool NetworkTableEntry::SetValue(const Value& value) { - return SetEntryValue(m_handle, value); -} - -inline bool NetworkTableEntry::SetBoolean(bool value, int64_t time) { - return nt::SetBoolean(m_handle, value, time); -} - -inline bool NetworkTableEntry::SetInteger(int64_t value, int64_t time) { - return nt::SetInteger(m_handle, value, time); -} - -inline bool NetworkTableEntry::SetFloat(float value, int64_t time) { - return nt::SetFloat(m_handle, value, time); -} - -inline bool NetworkTableEntry::SetDouble(double value, int64_t time) { - return nt::SetDouble(m_handle, value, time); -} - -inline bool NetworkTableEntry::SetString(std::string_view value, int64_t time) { - return nt::SetString(m_handle, value, time); -} - -inline bool NetworkTableEntry::SetRaw(std::span value, - int64_t time) { - return nt::SetRaw(m_handle, value, time); -} - -inline bool NetworkTableEntry::SetBooleanArray(std::span value, - int64_t time) { - return SetEntryValue(m_handle, Value::MakeBooleanArray(value, time)); -} - -inline bool NetworkTableEntry::SetBooleanArray(std::span value, - int64_t time) { - return nt::SetBooleanArray(m_handle, value, time); -} - -inline bool NetworkTableEntry::SetIntegerArray(std::span value, - int64_t time) { - return nt::SetIntegerArray(m_handle, value, time); -} - -inline bool NetworkTableEntry::SetFloatArray(std::span value, - int64_t time) { - return nt::SetFloatArray(m_handle, value, time); -} - -inline bool NetworkTableEntry::SetDoubleArray(std::span value, - int64_t time) { - return nt::SetDoubleArray(m_handle, value, time); -} - -inline bool NetworkTableEntry::SetStringArray( - std::span value, int64_t time) { - return nt::SetStringArray(m_handle, value, time); -} - -inline void NetworkTableEntry::SetPersistent() { - nt::SetTopicPersistent(nt::GetTopicFromHandle(m_handle), true); -} - -inline void NetworkTableEntry::ClearPersistent() { - nt::SetTopicPersistent(nt::GetTopicFromHandle(m_handle), false); -} - -inline bool NetworkTableEntry::IsPersistent() const { - return nt::GetTopicPersistent(nt::GetTopicFromHandle(m_handle)); -} - -inline void NetworkTableEntry::Unpublish() { - return nt::Unpublish(m_handle); -} - -} // namespace nt diff --git a/ntcore/src/main/native/include/networktables/NetworkTableInstance.h b/ntcore/src/main/native/include/networktables/NetworkTableInstance.h index 60cf7841de8..bd522f70168 100644 --- a/ntcore/src/main/native/include/networktables/NetworkTableInstance.h +++ b/ntcore/src/main/native/include/networktables/NetworkTableInstance.h @@ -4,11 +4,9 @@ #pragma once -#include #include #include #include -#include #include #include #include @@ -109,14 +107,14 @@ class NetworkTableInstance final { /** * Construct invalid instance. */ - NetworkTableInstance() noexcept; + NetworkTableInstance() noexcept = default; /** * Construct from native handle. * - * @param inst Native handle + * @param handle Native handle */ - explicit NetworkTableInstance(NT_Inst inst) noexcept; + explicit NetworkTableInstance(NT_Inst handle) noexcept : m_handle{handle} {} /** * Determines if the native handle is valid. @@ -130,28 +128,37 @@ class NetworkTableInstance final { * * @return Global default instance */ - static NetworkTableInstance GetDefault(); + static NetworkTableInstance GetDefault() { + return NetworkTableInstance{GetDefaultInstance()}; + } /** * Create an instance. * * @return Newly created instance */ - static NetworkTableInstance Create(); + static NetworkTableInstance Create() { + return NetworkTableInstance{CreateInstance()}; + } /** * Destroys an instance (note: this has global effect). * * @param inst Instance */ - static void Destroy(NetworkTableInstance& inst); + static void Destroy(NetworkTableInstance& inst) { + if (inst.m_handle != 0) { + DestroyInstance(inst.m_handle); + inst.m_handle = 0; + } + } /** * Gets the native handle for the entry. * * @return Native handle */ - NT_Inst GetHandle() const; + NT_Inst GetHandle() const { return m_handle; } /** * Gets a "generic" (untyped) topic. @@ -256,7 +263,9 @@ class NetworkTableInstance final { * @return Topic */ template - ProtobufTopic GetProtobufTopic(std::string_view name) const; + ProtobufTopic GetProtobufTopic(std::string_view name) const { + return ProtobufTopic{GetTopic(name)}; + } /** * Gets a raw struct serialized value topic. @@ -267,7 +276,9 @@ class NetworkTableInstance final { */ template requires wpi::StructSerializable - StructTopic GetStructTopic(std::string_view name, I... info) const; + StructTopic GetStructTopic(std::string_view name, I... info) const { + return StructTopic{GetTopic(name), std::move(info)...}; + } /** * Gets a raw struct serialized array topic. @@ -279,7 +290,9 @@ class NetworkTableInstance final { template requires wpi::StructSerializable StructArrayTopic GetStructArrayTopic(std::string_view name, - I... info) const; + I... info) const { + return StructArrayTopic{GetTopic(name), std::move(info)...}; + } /** * Get Published Topics. @@ -288,7 +301,10 @@ class NetworkTableInstance final { * * @return Array of topics. */ - std::vector GetTopics(); + std::vector GetTopics() { + auto handles = ::nt::GetTopics(m_handle, "", 0); + return {handles.begin(), handles.end()}; + } /** * Get Published Topics. @@ -300,7 +316,10 @@ class NetworkTableInstance final { * starts with this string are returned * @return Array of topics. */ - std::vector GetTopics(std::string_view prefix); + std::vector GetTopics(std::string_view prefix) { + auto handles = ::nt::GetTopics(m_handle, prefix, 0); + return {handles.begin(), handles.end()}; + } /** * Get Published Topics. @@ -314,7 +333,10 @@ class NetworkTableInstance final { * as a "don't care" * @return Array of topics. */ - std::vector GetTopics(std::string_view prefix, unsigned int types); + std::vector GetTopics(std::string_view prefix, unsigned int types) { + auto handles = ::nt::GetTopics(m_handle, prefix, types); + return {handles.begin(), handles.end()}; + } /** * Get Published Topics. @@ -328,7 +350,10 @@ class NetworkTableInstance final { * @return Array of topic handles. */ std::vector GetTopics(std::string_view prefix, - std::span types); + std::span types) { + auto handles = ::nt::GetTopics(m_handle, prefix, types); + return {handles.begin(), handles.end()}; + } /** * Get Topic Information about multiple topics. @@ -337,7 +362,9 @@ class NetworkTableInstance final { * * @return Array of topic information. */ - std::vector GetTopicInfo(); + std::vector GetTopicInfo() { + return ::nt::GetTopicInfo(m_handle, "", 0); + } /** * Get Topic Information about multiple topics. @@ -350,7 +377,9 @@ class NetworkTableInstance final { * starts with this string are returned * @return Array of topic information. */ - std::vector GetTopicInfo(std::string_view prefix); + std::vector GetTopicInfo(std::string_view prefix) { + return ::nt::GetTopicInfo(m_handle, prefix, 0); + } /** * Get Topic Information about multiple topics. @@ -366,7 +395,9 @@ class NetworkTableInstance final { * @return Array of topic information. */ std::vector GetTopicInfo(std::string_view prefix, - unsigned int types); + unsigned int types) { + return ::nt::GetTopicInfo(m_handle, prefix, types); + } /** * Get Topic Information about multiple topics. @@ -381,7 +412,9 @@ class NetworkTableInstance final { * @return Array of topic information. */ std::vector GetTopicInfo(std::string_view prefix, - std::span types); + std::span types) { + return ::nt::GetTopicInfo(m_handle, prefix, types); + } /** * Gets the entry for a key. @@ -389,7 +422,9 @@ class NetworkTableInstance final { * @param name Key * @return Network table entry. */ - NetworkTableEntry GetEntry(std::string_view name); + NetworkTableEntry GetEntry(std::string_view name) { + return NetworkTableEntry{::nt::GetEntry(m_handle, name)}; + } /** * Gets the table with the specified key. @@ -409,7 +444,9 @@ class NetworkTableInstance final { * * @param listener Listener handle to remove */ - static void RemoveListener(NT_Listener listener); + static void RemoveListener(NT_Listener listener) { + ::nt::RemoveListener(listener); + } /** * Wait for the listener queue to be empty. This is primarily @@ -421,7 +458,9 @@ class NetworkTableInstance final { * a negative value to block indefinitely * @return False if timed out, otherwise true. */ - bool WaitForListenerQueue(double timeout); + bool WaitForListenerQueue(double timeout) { + return ::nt::WaitForListenerQueue(m_handle, timeout); + } /** * Add a connection listener. The callback function is called asynchronously @@ -433,7 +472,12 @@ class NetworkTableInstance final { * @return Listener handle */ NT_Listener AddConnectionListener(bool immediate_notify, - ListenerCallback callback) const; + ListenerCallback callback) const { + return ::nt::AddListener( + m_handle, + NT_EVENT_CONNECTION | (immediate_notify ? NT_EVENT_IMMEDIATE : 0), + std::move(callback)); + } /** * Add a time synchronization listener. The callback function is called @@ -447,7 +491,12 @@ class NetworkTableInstance final { * @return Listener handle */ NT_Listener AddTimeSyncListener(bool immediate_notify, - ListenerCallback callback) const; + ListenerCallback callback) const { + return ::nt::AddListener( + m_handle, + NT_EVENT_TIMESYNC | (immediate_notify ? NT_EVENT_IMMEDIATE : 0), + std::move(callback)); + } /** * Add a listener for changes on a particular topic. The callback @@ -523,7 +572,10 @@ class NetworkTableInstance final { * @return Listener handle */ NT_Listener AddListener(std::span prefixes, - int eventMask, ListenerCallback listener); + int eventMask, ListenerCallback listener) { + return ::nt::AddListener(m_handle, prefixes, eventMask, + std::move(listener)); + } /** @} */ @@ -537,20 +589,20 @@ class NetworkTableInstance final { * * @return Bitmask of NetworkMode. */ - unsigned int GetNetworkMode() const; + unsigned int GetNetworkMode() const { return ::nt::GetNetworkMode(m_handle); } /** * Starts local-only operation. Prevents calls to StartServer or StartClient * from taking effect. Has no effect if StartServer or StartClient * has already been called. */ - void StartLocal(); + void StartLocal() { ::nt::StartLocal(m_handle); } /** * Stops local-only operation. StartServer or StartClient can be called after * this call to start a server or client. */ - void StopLocal(); + void StopLocal() { ::nt::StopLocal(m_handle); } /** * Starts a server using the specified filename, listening address, and port. @@ -565,12 +617,14 @@ class NetworkTableInstance final { void StartServer(std::string_view persist_filename = "networktables.json", const char* listen_address = "", unsigned int port3 = kDefaultPort3, - unsigned int port4 = kDefaultPort4); + unsigned int port4 = kDefaultPort4) { + ::nt::StartServer(m_handle, persist_filename, listen_address, port3, port4); + } /** * Stops the server if it is running. */ - void StopServer(); + void StopServer() { ::nt::StopServer(m_handle); } /** * Starts a NT3 client. Use SetServer or SetServerTeam to set the server name @@ -578,7 +632,9 @@ class NetworkTableInstance final { * * @param identity network identity to advertise (cannot be empty string) */ - void StartClient3(std::string_view identity); + void StartClient3(std::string_view identity) { + ::nt::StartClient3(m_handle, identity); + } /** * Starts a NT4 client. Use SetServer or SetServerTeam to set the server name @@ -586,12 +642,14 @@ class NetworkTableInstance final { * * @param identity network identity to advertise (cannot be empty string) */ - void StartClient4(std::string_view identity); + void StartClient4(std::string_view identity) { + ::nt::StartClient4(m_handle, identity); + } /** * Stops the client if it is running. */ - void StopClient(); + void StopClient() { ::nt::StopClient(m_handle); } /** * Sets server address and port for client (without restarting client). @@ -599,7 +657,9 @@ class NetworkTableInstance final { * @param server_name server name (UTF-8 string) * @param port port to communicate over (0 = default) */ - void SetServer(std::string_view server_name, unsigned int port = 0); + void SetServer(std::string_view server_name, unsigned int port = 0) { + ::nt::SetServer(m_handle, server_name, port); + } /** * Sets server addresses and ports for client (without restarting client). @@ -608,7 +668,9 @@ class NetworkTableInstance final { * @param servers array of server address and port pairs */ void SetServer( - std::span> servers); + std::span> servers) { + ::nt::SetServer(m_handle, servers); + } /** * Sets server addresses and port for client (without restarting client). @@ -627,13 +689,15 @@ class NetworkTableInstance final { * @param team team number * @param port port to communicate over (0 = default) */ - void SetServerTeam(unsigned int team, unsigned int port = 0); + void SetServerTeam(unsigned int team, unsigned int port = 0) { + ::nt::SetServerTeam(m_handle, team, port); + } /** * Disconnects the client if it's running and connected. This will * automatically start reconnection attempts to the current server list. */ - void Disconnect(); + void Disconnect() { ::nt::Disconnect(m_handle); } /** * Starts requesting server address from Driver Station. @@ -642,18 +706,20 @@ class NetworkTableInstance final { * * @param port server port to use in combination with IP from DS (0 = default) */ - void StartDSClient(unsigned int port = 0); + void StartDSClient(unsigned int port = 0) { + ::nt::StartDSClient(m_handle, port); + } /** * Stops requesting server address from Driver Station. */ - void StopDSClient(); + void StopDSClient() { ::nt::StopDSClient(m_handle); } /** * Flushes all updated values immediately to the local client/server. This * does not flush to the network. */ - void FlushLocal() const; + void FlushLocal() const { ::nt::FlushLocal(m_handle); } /** * Flushes all updated values immediately to the network. @@ -661,7 +727,7 @@ class NetworkTableInstance final { * This is primarily useful for synchronizing network updates with * user code. */ - void Flush() const; + void Flush() const { ::nt::Flush(m_handle); } /** * Get information on the currently established network connections. @@ -669,14 +735,16 @@ class NetworkTableInstance final { * * @return array of connection information */ - std::vector GetConnections() const; + std::vector GetConnections() const { + return ::nt::GetConnections(m_handle); + } /** * Return whether or not the instance is connected to another node. * * @return True if connected. */ - bool IsConnected() const; + bool IsConnected() const { return ::nt::IsConnected(m_handle); } /** * Get the time offset between server time and local time. Add this value to @@ -689,7 +757,9 @@ class NetworkTableInstance final { * * @return Time offset in microseconds (optional) */ - std::optional GetServerTimeOffset() const; + std::optional GetServerTimeOffset() const { + return ::nt::GetServerTimeOffset(m_handle); + } /** @} */ @@ -710,14 +780,18 @@ class NetworkTableInstance final { */ NT_DataLogger StartEntryDataLog(wpi::log::DataLog& log, std::string_view prefix, - std::string_view logPrefix); + std::string_view logPrefix) { + return ::nt::StartEntryDataLog(m_handle, log, prefix, logPrefix); + } /** * Stops logging entry changes to a DataLog. * * @param logger data logger handle */ - static void StopEntryDataLog(NT_DataLogger logger); + static void StopEntryDataLog(NT_DataLogger logger) { + ::nt::StopEntryDataLog(logger); + } /** * Starts logging connection changes to a DataLog. @@ -728,14 +802,18 @@ class NetworkTableInstance final { * @return Data logger handle */ NT_ConnectionDataLogger StartConnectionDataLog(wpi::log::DataLog& log, - std::string_view name); + std::string_view name) { + return ::nt::StartConnectionDataLog(m_handle, log, name); + } /** * Stops logging connection changes to a DataLog. * * @param logger data logger handle */ - static void StopConnectionDataLog(NT_ConnectionDataLogger logger); + static void StopConnectionDataLog(NT_ConnectionDataLogger logger) { + ::nt::StopConnectionDataLog(logger); + } /** @} */ @@ -757,7 +835,9 @@ class NetworkTableInstance final { * @return Listener handle */ NT_Listener AddLogger(unsigned int minLevel, unsigned int maxLevel, - ListenerCallback func); + ListenerCallback func) { + return ::nt::AddLogger(m_handle, minLevel, maxLevel, std::move(func)); + } /** @} */ @@ -775,7 +855,9 @@ class NetworkTableInstance final { * schema) * @return True if schema already registered */ - bool HasSchema(std::string_view name) const; + bool HasSchema(std::string_view name) const { + return ::nt::HasSchema(m_handle, name); + } /** * Registers a data schema. Data schemas provide information for how a @@ -792,7 +874,9 @@ class NetworkTableInstance final { * @param schema Schema data */ void AddSchema(std::string_view name, std::string_view type, - std::span schema); + std::span schema) { + ::nt::AddSchema(m_handle, name, type, schema); + } /** * Registers a data schema. Data schemas provide information for how a @@ -809,7 +893,15 @@ class NetworkTableInstance final { * @param schema Schema data */ void AddSchema(std::string_view name, std::string_view type, - std::string_view schema); + std::string_view schema) { + ::nt::AddSchema(m_handle, name, type, schema); + } + +// Suppress unused-lambda-capture warning on AddSchema() call +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-lambda-capture" +#endif /** * Registers a protobuf schema. Duplicate calls to this function with the same @@ -819,7 +911,13 @@ class NetworkTableInstance final { * @param msg protobuf message */ template - void AddProtobufSchema(wpi::ProtobufMessage& msg); + void AddProtobufSchema(wpi::ProtobufMessage& msg) { + msg.ForEachProtobufDescriptor( + [this](auto typeString) { return HasSchema(typeString); }, + [this](auto typeString, auto schema) { + AddSchema(typeString, "proto:FileDescriptorProto", schema); + }); + } /** * Registers a struct schema. Duplicate calls to this function with the same @@ -830,7 +928,17 @@ class NetworkTableInstance final { */ template requires wpi::StructSerializable - void AddStructSchema(const I&... info); + void AddStructSchema(const I&... info) { + wpi::ForEachStructSchema( + [this](auto typeString, auto schema) { + AddSchema(typeString, "structschema", schema); + }, + info...); + } + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif /** * Equality operator. Returns true if both instances refer to the same @@ -844,5 +952,3 @@ class NetworkTableInstance final { }; } // namespace nt - -#include "networktables/NetworkTableInstance.inc" diff --git a/ntcore/src/main/native/include/networktables/NetworkTableInstance.inc b/ntcore/src/main/native/include/networktables/NetworkTableInstance.inc deleted file mode 100644 index 20b5c0b58ae..00000000000 --- a/ntcore/src/main/native/include/networktables/NetworkTableInstance.inc +++ /dev/null @@ -1,291 +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 -#include -#include - -#include "networktables/NetworkTableInstance.h" -#include "networktables/Topic.h" -#include "ntcore_c.h" - -namespace nt { - -inline NetworkTableInstance::NetworkTableInstance() noexcept {} - -inline NetworkTableInstance::NetworkTableInstance(NT_Inst handle) noexcept - : m_handle{handle} {} - -inline NetworkTableInstance NetworkTableInstance::GetDefault() { - return NetworkTableInstance{GetDefaultInstance()}; -} - -inline NetworkTableInstance NetworkTableInstance::Create() { - return NetworkTableInstance{CreateInstance()}; -} - -inline void NetworkTableInstance::Destroy(NetworkTableInstance& inst) { - if (inst.m_handle != 0) { - DestroyInstance(inst.m_handle); - inst.m_handle = 0; - } -} - -inline NT_Inst NetworkTableInstance::GetHandle() const { - return m_handle; -} - -template -inline ProtobufTopic NetworkTableInstance::GetProtobufTopic( - std::string_view name) const { - return ProtobufTopic{GetTopic(name)}; -} - -template - requires wpi::StructSerializable -inline StructTopic NetworkTableInstance::GetStructTopic( - std::string_view name, I... info) const { - return StructTopic{GetTopic(name), std::move(info)...}; -} - -template - requires wpi::StructSerializable -inline StructArrayTopic NetworkTableInstance::GetStructArrayTopic( - std::string_view name, I... info) const { - return StructArrayTopic{GetTopic(name), std::move(info)...}; -} - -inline std::vector NetworkTableInstance::GetTopics() { - auto handles = ::nt::GetTopics(m_handle, "", 0); - return {handles.begin(), handles.end()}; -} - -inline std::vector NetworkTableInstance::GetTopics( - std::string_view prefix) { - auto handles = ::nt::GetTopics(m_handle, prefix, 0); - return {handles.begin(), handles.end()}; -} - -inline std::vector NetworkTableInstance::GetTopics( - std::string_view prefix, unsigned int types) { - auto handles = ::nt::GetTopics(m_handle, prefix, types); - return {handles.begin(), handles.end()}; -} - -inline std::vector NetworkTableInstance::GetTopics( - std::string_view prefix, std::span types) { - auto handles = ::nt::GetTopics(m_handle, prefix, types); - return {handles.begin(), handles.end()}; -} - -inline std::vector NetworkTableInstance::GetTopicInfo() { - return ::nt::GetTopicInfo(m_handle, "", 0); -} - -inline std::vector NetworkTableInstance::GetTopicInfo( - std::string_view prefix) { - return ::nt::GetTopicInfo(m_handle, prefix, 0); -} - -inline std::vector NetworkTableInstance::GetTopicInfo( - std::string_view prefix, unsigned int types) { - return ::nt::GetTopicInfo(m_handle, prefix, types); -} - -inline std::vector NetworkTableInstance::GetTopicInfo( - std::string_view prefix, std::span types) { - return ::nt::GetTopicInfo(m_handle, prefix, types); -} - -inline NetworkTableEntry NetworkTableInstance::GetEntry(std::string_view name) { - return NetworkTableEntry{::nt::GetEntry(m_handle, name)}; -} - -inline bool NetworkTableInstance::WaitForListenerQueue(double timeout) { - return ::nt::WaitForListenerQueue(m_handle, timeout); -} - -inline void NetworkTableInstance::RemoveListener(NT_Listener listener) { - ::nt::RemoveListener(listener); -} - -inline NT_Listener NetworkTableInstance::AddConnectionListener( - bool immediate_notify, ListenerCallback callback) const { - return ::nt::AddListener( - m_handle, - NT_EVENT_CONNECTION | (immediate_notify ? NT_EVENT_IMMEDIATE : 0), - std::move(callback)); -} - -inline NT_Listener NetworkTableInstance::AddTimeSyncListener( - bool immediate_notify, ListenerCallback callback) const { - return ::nt::AddListener( - m_handle, NT_EVENT_TIMESYNC | (immediate_notify ? NT_EVENT_IMMEDIATE : 0), - std::move(callback)); -} - -inline NT_Listener NetworkTableInstance::AddListener( - std::span prefixes, int eventMask, - ListenerCallback listener) { - return ::nt::AddListener(m_handle, prefixes, eventMask, std::move(listener)); -} - -inline unsigned int NetworkTableInstance::GetNetworkMode() const { - return ::nt::GetNetworkMode(m_handle); -} - -inline void NetworkTableInstance::StartLocal() { - ::nt::StartLocal(m_handle); -} - -inline void NetworkTableInstance::StopLocal() { - ::nt::StopLocal(m_handle); -} - -inline void NetworkTableInstance::StartServer(std::string_view persist_filename, - const char* listen_address, - unsigned int port3, - unsigned int port4) { - ::nt::StartServer(m_handle, persist_filename, listen_address, port3, port4); -} - -inline void NetworkTableInstance::StopServer() { - ::nt::StopServer(m_handle); -} - -inline void NetworkTableInstance::StartClient3(std::string_view identity) { - ::nt::StartClient3(m_handle, identity); -} - -inline void NetworkTableInstance::StartClient4(std::string_view identity) { - ::nt::StartClient4(m_handle, identity); -} - -inline void NetworkTableInstance::StopClient() { - ::nt::StopClient(m_handle); -} - -inline void NetworkTableInstance::SetServer(std::string_view server_name, - unsigned int port) { - ::nt::SetServer(m_handle, server_name, port); -} - -inline void NetworkTableInstance::SetServer( - std::span> servers) { - ::nt::SetServer(m_handle, servers); -} - -inline void NetworkTableInstance::SetServerTeam(unsigned int team, - unsigned int port) { - ::nt::SetServerTeam(m_handle, team, port); -} - -inline void NetworkTableInstance::Disconnect() { - ::nt::Disconnect(m_handle); -} - -inline void NetworkTableInstance::StartDSClient(unsigned int port) { - ::nt::StartDSClient(m_handle, port); -} - -inline void NetworkTableInstance::StopDSClient() { - ::nt::StopDSClient(m_handle); -} - -inline void NetworkTableInstance::FlushLocal() const { - ::nt::FlushLocal(m_handle); -} - -inline void NetworkTableInstance::Flush() const { - ::nt::Flush(m_handle); -} - -inline std::vector NetworkTableInstance::GetConnections() - const { - return ::nt::GetConnections(m_handle); -} - -inline bool NetworkTableInstance::IsConnected() const { - return ::nt::IsConnected(m_handle); -} - -inline std::optional NetworkTableInstance::GetServerTimeOffset() - const { - return ::nt::GetServerTimeOffset(m_handle); -} - -inline NT_DataLogger NetworkTableInstance::StartEntryDataLog( - wpi::log::DataLog& log, std::string_view prefix, - std::string_view logPrefix) { - return ::nt::StartEntryDataLog(m_handle, log, prefix, logPrefix); -} - -inline void NetworkTableInstance::StopEntryDataLog(NT_DataLogger logger) { - ::nt::StopEntryDataLog(logger); -} - -inline NT_ConnectionDataLogger NetworkTableInstance::StartConnectionDataLog( - wpi::log::DataLog& log, std::string_view name) { - return ::nt::StartConnectionDataLog(m_handle, log, name); -} - -inline void NetworkTableInstance::StopConnectionDataLog( - NT_ConnectionDataLogger logger) { - ::nt::StopConnectionDataLog(logger); -} - -inline NT_Listener NetworkTableInstance::AddLogger(unsigned int min_level, - unsigned int max_level, - ListenerCallback func) { - return ::nt::AddLogger(m_handle, min_level, max_level, std::move(func)); -} - -inline bool NetworkTableInstance::HasSchema(std::string_view name) const { - return ::nt::HasSchema(m_handle, name); -} - -inline void NetworkTableInstance::AddSchema(std::string_view name, - std::string_view type, - std::span schema) { - ::nt::AddSchema(m_handle, name, type, schema); -} - -inline void NetworkTableInstance::AddSchema(std::string_view name, - std::string_view type, - std::string_view schema) { - ::nt::AddSchema(m_handle, name, type, schema); -} - -// Suppress unused-lambda-capture warning on AddSchema() call -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-lambda-capture" -#endif - -template -void NetworkTableInstance::AddProtobufSchema(wpi::ProtobufMessage& msg) { - msg.ForEachProtobufDescriptor( - [this](auto typeString) { return HasSchema(typeString); }, - [this](auto typeString, auto schema) { - AddSchema(typeString, "proto:FileDescriptorProto", schema); - }); -} - -template - requires wpi::StructSerializable -void NetworkTableInstance::AddStructSchema(const I&... info) { - wpi::ForEachStructSchema( - [this](auto typeString, auto schema) { - AddSchema(typeString, "structschema", schema); - }, - info...); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -} // namespace nt diff --git a/ntcore/src/main/native/include/networktables/NetworkTableListener.h b/ntcore/src/main/native/include/networktables/NetworkTableListener.h index 1a8cf1fa46a..fc0cf65e600 100644 --- a/ntcore/src/main/native/include/networktables/NetworkTableListener.h +++ b/ntcore/src/main/native/include/networktables/NetworkTableListener.h @@ -4,11 +4,15 @@ #pragma once -#include #include #include +#include #include +#include "networktables/MultiSubscriber.h" +#include "networktables/NetworkTableEntry.h" +#include "networktables/NetworkTableInstance.h" +#include "networktables/Topic.h" #include "ntcore_cpp.h" namespace nt { @@ -42,7 +46,10 @@ class NetworkTableListener final { */ static NetworkTableListener CreateListener( NetworkTableInstance inst, std::span prefixes, - unsigned int mask, ListenerCallback listener); + unsigned int mask, ListenerCallback listener) { + return NetworkTableListener{::nt::AddListener(inst.GetHandle(), prefixes, + mask, std::move(listener))}; + } /** * Create a listener for changes on a particular topic. This creates a @@ -54,7 +61,10 @@ class NetworkTableListener final { * @return Listener */ static NetworkTableListener CreateListener(Topic topic, unsigned int mask, - ListenerCallback listener); + ListenerCallback listener) { + return NetworkTableListener{ + nt::AddListener(topic.GetHandle(), mask, std::move(listener))}; + } /** * Create a listener for topic changes on a subscriber. This does NOT keep the @@ -67,7 +77,10 @@ class NetworkTableListener final { */ static NetworkTableListener CreateListener(Subscriber& subscriber, unsigned int mask, - ListenerCallback listener); + ListenerCallback listener) { + return NetworkTableListener{ + ::nt::AddListener(subscriber.GetHandle(), mask, std::move(listener))}; + } /** * Create a listener for topic changes on a subscriber. This does NOT keep the @@ -80,7 +93,10 @@ class NetworkTableListener final { */ static NetworkTableListener CreateListener(MultiSubscriber& subscriber, unsigned int mask, - ListenerCallback listener); + ListenerCallback listener) { + return NetworkTableListener{ + ::nt::AddListener(subscriber.GetHandle(), mask, std::move(listener))}; + } /** * Create a listener for topic changes on an entry. @@ -92,7 +108,10 @@ class NetworkTableListener final { */ static NetworkTableListener CreateListener(NetworkTableEntry& entry, unsigned int mask, - ListenerCallback listener); + ListenerCallback listener) { + return NetworkTableListener{ + ::nt::AddListener(entry.GetHandle(), mask, std::move(listener))}; + } /** * Create a connection listener. @@ -104,7 +123,12 @@ class NetworkTableListener final { */ static NetworkTableListener CreateConnectionListener( NetworkTableInstance inst, bool immediate_notify, - ListenerCallback listener); + ListenerCallback listener) { + return NetworkTableListener{::nt::AddListener( + inst.GetHandle(), + NT_EVENT_CONNECTION | (immediate_notify ? NT_EVENT_IMMEDIATE : 0), + std::move(listener))}; + } /** * Create a time synchronization listener. @@ -115,9 +139,14 @@ class NetworkTableListener final { * @param listener listener function * @return Listener */ - static NetworkTableListener CreateTimeSyncListener(NetworkTableInstance inst, - bool immediate_notify, - ListenerCallback listener); + static NetworkTableListener CreateTimeSyncListener( + NetworkTableInstance inst, bool immediate_notify, + ListenerCallback listener) { + return NetworkTableListener{::nt::AddListener( + inst.GetHandle(), + NT_EVENT_TIMESYNC | (immediate_notify ? NT_EVENT_IMMEDIATE : 0), + std::move(listener))}; + } /** * Create a listener for log messages. By default, log messages are sent to @@ -136,13 +165,32 @@ class NetworkTableListener final { static NetworkTableListener CreateLogger(NetworkTableInstance inst, unsigned int minLevel, unsigned int maxLevel, - ListenerCallback listener); + ListenerCallback listener) { + return NetworkTableListener{::nt::AddLogger(inst.GetHandle(), minLevel, + maxLevel, std::move(listener))}; + } NetworkTableListener(const NetworkTableListener&) = delete; NetworkTableListener& operator=(const NetworkTableListener&) = delete; - NetworkTableListener(NetworkTableListener&& rhs); - NetworkTableListener& operator=(NetworkTableListener&& rhs); - ~NetworkTableListener(); + + NetworkTableListener(NetworkTableListener&& rhs) : m_handle(rhs.m_handle) { + rhs.m_handle = 0; + } + + NetworkTableListener& operator=(NetworkTableListener&& rhs) { + if (m_handle != 0) { + nt::RemoveListener(m_handle); + } + m_handle = rhs.m_handle; + rhs.m_handle = 0; + return *this; + } + + ~NetworkTableListener() { + if (m_handle != 0) { + nt::RemoveListener(m_handle); + } + } explicit operator bool() const { return m_handle != 0; } @@ -163,7 +211,13 @@ class NetworkTableListener final { * a negative value to block indefinitely * @return False if timed out, otherwise true. */ - bool WaitForQueue(double timeout); + bool WaitForQueue(double timeout) { + if (m_handle != 0) { + return nt::WaitForListenerQueue(m_handle, timeout); + } else { + return false; + } + } private: explicit NetworkTableListener(NT_Listener handle) : m_handle{handle} {} @@ -185,14 +239,32 @@ class NetworkTableListenerPoller final { * * @param inst Instance */ - explicit NetworkTableListenerPoller(NetworkTableInstance inst); + explicit NetworkTableListenerPoller(NetworkTableInstance inst) + : m_handle(nt::CreateListenerPoller(inst.GetHandle())) {} NetworkTableListenerPoller(const NetworkTableListenerPoller&) = delete; NetworkTableListenerPoller& operator=(const NetworkTableListenerPoller&) = delete; - NetworkTableListenerPoller(NetworkTableListenerPoller&& rhs); - NetworkTableListenerPoller& operator=(NetworkTableListenerPoller&& rhs); - ~NetworkTableListenerPoller(); + + NetworkTableListenerPoller(NetworkTableListenerPoller&& rhs) + : m_handle(rhs.m_handle) { + rhs.m_handle = 0; + } + + NetworkTableListenerPoller& operator=(NetworkTableListenerPoller&& rhs) { + if (m_handle != 0) { + nt::DestroyListenerPoller(m_handle); + } + m_handle = rhs.m_handle; + rhs.m_handle = 0; + return *this; + } + + ~NetworkTableListenerPoller() { + if (m_handle != 0) { + nt::DestroyListenerPoller(m_handle); + } + } explicit operator bool() const { return m_handle != 0; } @@ -213,7 +285,9 @@ class NetworkTableListenerPoller final { * @return Listener handle */ NT_Listener AddListener(std::span prefixes, - unsigned int mask); + unsigned int mask) { + return nt::AddPolledListener(m_handle, prefixes, mask); + } /** * Start listening to changes to a particular topic. This creates a @@ -223,7 +297,9 @@ class NetworkTableListenerPoller final { * @param mask Bitmask of EventFlags values * @return Listener handle */ - NT_Listener AddListener(Topic topic, unsigned int mask); + NT_Listener AddListener(Topic topic, unsigned int mask) { + return ::nt::AddPolledListener(m_handle, topic.GetHandle(), mask); + } /** * Start listening to topic changes on a subscriber. This does NOT keep the @@ -233,7 +309,9 @@ class NetworkTableListenerPoller final { * @param mask Bitmask of EventFlags values * @return Listener handle */ - NT_Listener AddListener(Subscriber& subscriber, unsigned int mask); + NT_Listener AddListener(Subscriber& subscriber, unsigned int mask) { + return ::nt::AddPolledListener(m_handle, subscriber.GetHandle(), mask); + } /** * Start listening to topic changes on a subscriber. This does NOT keep the @@ -243,7 +321,9 @@ class NetworkTableListenerPoller final { * @param mask Bitmask of EventFlags values * @return Listener handle */ - NT_Listener AddListener(MultiSubscriber& subscriber, unsigned int mask); + NT_Listener AddListener(MultiSubscriber& subscriber, unsigned int mask) { + return ::nt::AddPolledListener(m_handle, subscriber.GetHandle(), mask); + } /** * Start listening to topic changes on an entry. @@ -252,7 +332,9 @@ class NetworkTableListenerPoller final { * @param mask Bitmask of EventFlags values * @return Listener handle */ - NT_Listener AddListener(NetworkTableEntry& entry, unsigned int mask); + NT_Listener AddListener(NetworkTableEntry& entry, unsigned int mask) { + return ::nt::AddPolledListener(m_handle, entry.GetHandle(), mask); + } /** * Add a connection listener. The callback function is called asynchronously @@ -262,7 +344,11 @@ class NetworkTableListenerPoller final { * @param immediate_notify notify listener of all existing connections * @return Listener handle */ - NT_Listener AddConnectionListener(bool immediate_notify); + NT_Listener AddConnectionListener(bool immediate_notify) { + return ::nt::AddPolledListener( + m_handle, ::nt::GetInstanceFromHandle(m_handle), + NT_EVENT_CONNECTION | (immediate_notify ? NT_EVENT_IMMEDIATE : 0)); + } /** * Add a time synchronization listener. The callback function is called @@ -274,7 +360,11 @@ class NetworkTableListenerPoller final { * value * @return Listener handle */ - NT_Listener AddTimeSyncListener(bool immediate_notify); + NT_Listener AddTimeSyncListener(bool immediate_notify) { + return ::nt::AddPolledListener( + m_handle, ::nt::GetInstanceFromHandle(m_handle), + NT_EVENT_TIMESYNC | (immediate_notify ? NT_EVENT_IMMEDIATE : 0)); + } /** * Add logger callback function. By default, log messages are sent to stderr; @@ -287,26 +377,26 @@ class NetworkTableListenerPoller final { * @param maxLevel maximum log level * @return Listener handle */ - NT_Listener AddLogger(unsigned int minLevel, unsigned int maxLevel); + NT_Listener AddLogger(unsigned int minLevel, unsigned int maxLevel) { + return ::nt::AddPolledLogger(m_handle, minLevel, maxLevel); + } /** * Remove a listener. * * @param listener Listener handle */ - void RemoveListener(NT_Listener listener); + void RemoveListener(NT_Listener listener) { ::nt::RemoveListener(listener); } /** * Read events. * * @return Events since the previous call to ReadQueue() */ - std::vector ReadQueue(); + std::vector ReadQueue() { return ::nt::ReadListenerQueue(m_handle); } private: NT_ListenerPoller m_handle{0}; }; } // namespace nt - -#include "NetworkTableListener.inc" diff --git a/ntcore/src/main/native/include/networktables/NetworkTableListener.inc b/ntcore/src/main/native/include/networktables/NetworkTableListener.inc deleted file mode 100644 index 5453d87584c..00000000000 --- a/ntcore/src/main/native/include/networktables/NetworkTableListener.inc +++ /dev/null @@ -1,184 +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 -#include -#include -#include - -#include "networktables/MultiSubscriber.h" -#include "networktables/NetworkTableEntry.h" -#include "networktables/NetworkTableInstance.h" -#include "networktables/NetworkTableListener.h" -#include "networktables/Topic.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline NetworkTableListener NetworkTableListener::CreateListener( - NetworkTableInstance inst, std::span prefixes, - unsigned int mask, ListenerCallback listener) { - return NetworkTableListener{ - ::nt::AddListener(inst.GetHandle(), prefixes, mask, std::move(listener))}; -} - -inline NetworkTableListener NetworkTableListener::CreateListener( - Topic topic, unsigned int mask, ListenerCallback listener) { - return NetworkTableListener{ - nt::AddListener(topic.GetHandle(), mask, std::move(listener))}; -} - -inline NetworkTableListener NetworkTableListener::CreateListener( - Subscriber& subscriber, unsigned int mask, ListenerCallback listener) { - return NetworkTableListener{ - ::nt::AddListener(subscriber.GetHandle(), mask, std::move(listener))}; -} - -inline NetworkTableListener NetworkTableListener::CreateListener( - MultiSubscriber& subscriber, unsigned int mask, ListenerCallback listener) { - return NetworkTableListener{ - ::nt::AddListener(subscriber.GetHandle(), mask, std::move(listener))}; -} - -inline NetworkTableListener NetworkTableListener::CreateListener( - NetworkTableEntry& entry, unsigned int mask, ListenerCallback listener) { - return NetworkTableListener{ - ::nt::AddListener(entry.GetHandle(), mask, std::move(listener))}; -} - -inline NetworkTableListener NetworkTableListener::CreateConnectionListener( - NetworkTableInstance inst, bool immediate_notify, - ListenerCallback listener) { - return NetworkTableListener{::nt::AddListener( - inst.GetHandle(), - NT_EVENT_CONNECTION | (immediate_notify ? NT_EVENT_IMMEDIATE : 0), - std::move(listener))}; -} - -inline NetworkTableListener NetworkTableListener::CreateTimeSyncListener( - NetworkTableInstance inst, bool immediate_notify, - ListenerCallback listener) { - return NetworkTableListener{::nt::AddListener( - inst.GetHandle(), - NT_EVENT_TIMESYNC | (immediate_notify ? NT_EVENT_IMMEDIATE : 0), - std::move(listener))}; -} - -inline NetworkTableListener NetworkTableListener::CreateLogger( - NetworkTableInstance inst, unsigned int minLevel, unsigned int maxLevel, - ListenerCallback listener) { - return NetworkTableListener{::nt::AddLogger(inst.GetHandle(), minLevel, - maxLevel, std::move(listener))}; -} - -inline NetworkTableListener::NetworkTableListener(NetworkTableListener&& rhs) - : m_handle(rhs.m_handle) { - rhs.m_handle = 0; -} - -inline NetworkTableListener& NetworkTableListener::operator=( - NetworkTableListener&& rhs) { - if (m_handle != 0) { - nt::RemoveListener(m_handle); - } - m_handle = rhs.m_handle; - rhs.m_handle = 0; - return *this; -} - -inline NetworkTableListener::~NetworkTableListener() { - if (m_handle != 0) { - nt::RemoveListener(m_handle); - } -} - -inline bool NetworkTableListener::WaitForQueue(double timeout) { - if (m_handle != 0) { - return nt::WaitForListenerQueue(m_handle, timeout); - } else { - return false; - } -} - -inline NetworkTableListenerPoller::NetworkTableListenerPoller( - NetworkTableInstance inst) - : m_handle(nt::CreateListenerPoller(inst.GetHandle())) {} - -inline NetworkTableListenerPoller::NetworkTableListenerPoller( - NetworkTableListenerPoller&& rhs) - : m_handle(rhs.m_handle) { - rhs.m_handle = 0; -} - -inline NetworkTableListenerPoller& NetworkTableListenerPoller::operator=( - NetworkTableListenerPoller&& rhs) { - if (m_handle != 0) { - nt::DestroyListenerPoller(m_handle); - } - m_handle = rhs.m_handle; - rhs.m_handle = 0; - return *this; -} - -inline NetworkTableListenerPoller::~NetworkTableListenerPoller() { - if (m_handle != 0) { - nt::DestroyListenerPoller(m_handle); - } -} - -inline NT_Listener NetworkTableListenerPoller::AddListener( - std::span prefixes, unsigned int mask) { - return nt::AddPolledListener(m_handle, prefixes, mask); -} - -inline NT_Listener NetworkTableListenerPoller::AddListener(Topic topic, - unsigned int mask) { - return ::nt::AddPolledListener(m_handle, topic.GetHandle(), mask); -} - -inline NT_Listener NetworkTableListenerPoller::AddListener( - Subscriber& subscriber, unsigned int mask) { - return ::nt::AddPolledListener(m_handle, subscriber.GetHandle(), mask); -} - -inline NT_Listener NetworkTableListenerPoller::AddListener( - MultiSubscriber& subscriber, unsigned int mask) { - return ::nt::AddPolledListener(m_handle, subscriber.GetHandle(), mask); -} - -inline NT_Listener NetworkTableListenerPoller::AddListener( - NetworkTableEntry& entry, unsigned int mask) { - return ::nt::AddPolledListener(m_handle, entry.GetHandle(), mask); -} - -inline NT_Listener NetworkTableListenerPoller::AddConnectionListener( - bool immediate_notify) { - return ::nt::AddPolledListener( - m_handle, ::nt::GetInstanceFromHandle(m_handle), - NT_EVENT_CONNECTION | (immediate_notify ? NT_EVENT_IMMEDIATE : 0)); -} - -inline NT_Listener NetworkTableListenerPoller::AddTimeSyncListener( - bool immediate_notify) { - return ::nt::AddPolledListener( - m_handle, ::nt::GetInstanceFromHandle(m_handle), - NT_EVENT_TIMESYNC | (immediate_notify ? NT_EVENT_IMMEDIATE : 0)); -} - -inline NT_Listener NetworkTableListenerPoller::AddLogger( - unsigned int minLevel, unsigned int maxLevel) { - return ::nt::AddPolledLogger(m_handle, minLevel, maxLevel); -} - -inline void NetworkTableListenerPoller::RemoveListener(NT_Listener listener) { - ::nt::RemoveListener(listener); -} - -inline std::vector NetworkTableListenerPoller::ReadQueue() { - return ::nt::ReadListenerQueue(m_handle); -} - -} // namespace nt diff --git a/ntcore/src/main/native/include/networktables/Topic.h b/ntcore/src/main/native/include/networktables/Topic.h index e34d7facc1c..a9360317185 100644 --- a/ntcore/src/main/native/include/networktables/Topic.h +++ b/ntcore/src/main/native/include/networktables/Topic.h @@ -56,14 +56,16 @@ class Topic { * * @return the topic's name */ - std::string GetName() const; + std::string GetName() const { return ::nt::GetTopicName(m_handle); } /** * Gets the type of the topic. * * @return the topic's type */ - NetworkTableType GetType() const; + NetworkTableType GetType() const { + return static_cast(::nt::GetTopicType(m_handle)); + } /** * Gets the type string of the topic. This may have more information @@ -71,28 +73,34 @@ class Topic { * * @return the topic's type */ - std::string GetTypeString() const; + std::string GetTypeString() const { + return ::nt::GetTopicTypeString(m_handle); + } /** * Make value persistent through server restarts. * * @param persistent True for persistent, false for not persistent. */ - void SetPersistent(bool persistent); + void SetPersistent(bool persistent) { + ::nt::SetTopicPersistent(m_handle, persistent); + } /** * Returns whether the value is persistent through server restarts. * * @return True if the value is persistent. */ - bool IsPersistent() const; + bool IsPersistent() const { return ::nt::GetTopicPersistent(m_handle); } /** * Make the server retain the topic even when there are no publishers. * * @param retained True for retained, false for not retained. */ - void SetRetained(bool retained); + void SetRetained(bool retained) { + ::nt::SetTopicRetained(m_handle, retained); + } /** * Returns whether the topic is retained by server when there are no @@ -100,7 +108,7 @@ class Topic { * * @return True if the topic is retained. */ - bool IsRetained() const; + bool IsRetained() const { return ::nt::GetTopicRetained(m_handle); } /** * Allow storage of the topic's last value, allowing the value to be read (and @@ -108,21 +116,21 @@ class Topic { * * @param cached True for cached, false for not cached. */ - void SetCached(bool cached); + void SetCached(bool cached) { ::nt::SetTopicCached(m_handle, cached); } /** * Returns whether the topic's last value is stored. * * @return True if the topic is cached. */ - bool IsCached() const; + bool IsCached() const { return ::nt::GetTopicCached(m_handle); } /** * Determines if the topic is currently being published. * * @return True if the topic exists, false otherwise. */ - bool Exists() const; + bool Exists() const { return nt::GetTopicExists(m_handle); } /** * Gets the current value of a property (as a JSON object). @@ -145,7 +153,9 @@ class Topic { * * @param name property name */ - void DeleteProperty(std::string_view name); + void DeleteProperty(std::string_view name) { + ::nt::DeleteTopicProperty(m_handle, name); + } /** * Gets all topic properties as a JSON object. Each key in the object @@ -164,14 +174,16 @@ class Topic { * @param properties JSON object with keys to add/update/delete * @return False if properties is not an object */ - bool SetProperties(const wpi::json& properties); + bool SetProperties(const wpi::json& properties) { + return ::nt::SetTopicProperties(m_handle, properties); + } /** * Gets combined information about the topic. * * @return Topic information */ - TopicInfo GetInfo() const; + TopicInfo GetInfo() const { return ::nt::GetTopicInfo(m_handle); } /** * Create a new subscriber to the topic. @@ -308,13 +320,23 @@ class Topic { /** NetworkTables subscriber. */ class Subscriber { public: - virtual ~Subscriber(); + virtual ~Subscriber() { ::nt::Release(m_subHandle); } Subscriber(const Subscriber&) = delete; Subscriber& operator=(const Subscriber&) = delete; - Subscriber(Subscriber&&); - Subscriber& operator=(Subscriber&&); + Subscriber(Subscriber&& rhs) : m_subHandle{rhs.m_subHandle} { + rhs.m_subHandle = 0; + } + + Subscriber& operator=(Subscriber&& rhs) { + if (m_subHandle != 0) { + ::nt::Release(m_subHandle); + } + m_subHandle = rhs.m_subHandle; + rhs.m_subHandle = 0; + return *this; + } /** * Determines if the native handle is valid. @@ -335,7 +357,7 @@ class Subscriber { * * @return True if the topic exists, false otherwise. */ - bool Exists() const; + bool Exists() const { return nt::GetTopicExists(m_subHandle); } /** * Gets the last time the value was changed. @@ -344,32 +366,49 @@ class Subscriber { * * @return Topic last change time */ - int64_t GetLastChange() const; + int64_t GetLastChange() const { + return ::nt::GetEntryLastChange(m_subHandle); + } /** * Gets the subscribed-to topic. * * @return Topic */ - Topic GetTopic() const; + Topic GetTopic() const { + return Topic{::nt::GetTopicFromHandle(m_subHandle)}; + } protected: Subscriber() = default; explicit Subscriber(NT_Subscriber handle) : m_subHandle{handle} {} NT_Subscriber m_subHandle{0}; + + private: + void anchor(); }; /** NetworkTables publisher. */ class Publisher { public: - virtual ~Publisher(); + virtual ~Publisher() { ::nt::Release(m_pubHandle); } Publisher(const Publisher&) = delete; Publisher& operator=(const Publisher&) = delete; - Publisher(Publisher&&); - Publisher& operator=(Publisher&&); + Publisher(Publisher&& rhs) : m_pubHandle{rhs.m_pubHandle} { + rhs.m_pubHandle = 0; + } + + Publisher& operator=(Publisher&& rhs) { + if (m_pubHandle != 0) { + ::nt::Release(m_pubHandle); + } + m_pubHandle = rhs.m_pubHandle; + rhs.m_pubHandle = 0; + return *this; + } /** * Determines if the native handle is valid. @@ -390,7 +429,9 @@ class Publisher { * * @return Topic */ - Topic GetTopic() const; + Topic GetTopic() const { + return Topic{::nt::GetTopicFromHandle(m_pubHandle)}; + } protected: Publisher() = default; @@ -398,8 +439,9 @@ class Publisher { /// NetworkTables handle. NT_Publisher m_pubHandle{0}; + + private: + void anchor(); }; } // namespace nt - -#include "networktables/Topic.inc" diff --git a/ntcore/src/main/native/include/networktables/Topic.inc b/ntcore/src/main/native/include/networktables/Topic.inc deleted file mode 100644 index 605f9d8d10d..00000000000 --- a/ntcore/src/main/native/include/networktables/Topic.inc +++ /dev/null @@ -1,118 +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 - -#include "networktables/NetworkTableType.h" -#include "networktables/Topic.h" -#include "ntcore_c.h" -#include "ntcore_cpp.h" - -namespace nt { - -inline std::string Topic::GetName() const { - return ::nt::GetTopicName(m_handle); -} - -inline NetworkTableType Topic::GetType() const { - return static_cast(::nt::GetTopicType(m_handle)); -} - -inline std::string Topic::GetTypeString() const { - return ::nt::GetTopicTypeString(m_handle); -} - -inline void Topic::SetPersistent(bool persistent) { - ::nt::SetTopicPersistent(m_handle, persistent); -} - -inline bool Topic::IsPersistent() const { - return ::nt::GetTopicPersistent(m_handle); -} - -inline void Topic::SetRetained(bool retained) { - ::nt::SetTopicRetained(m_handle, retained); -} - -inline bool Topic::IsRetained() const { - return ::nt::GetTopicRetained(m_handle); -} - -inline void Topic::SetCached(bool cached) { - ::nt::SetTopicCached(m_handle, cached); -} - -inline bool Topic::IsCached() const { - return ::nt::GetTopicCached(m_handle); -} - -inline bool Topic::Exists() const { - return nt::GetTopicExists(m_handle); -} - -inline void Topic::DeleteProperty(std::string_view name) { - ::nt::DeleteTopicProperty(m_handle, name); -} - -inline bool Topic::SetProperties(const wpi::json& properties) { - return ::nt::SetTopicProperties(m_handle, properties); -} - -inline TopicInfo Topic::GetInfo() const { - return ::nt::GetTopicInfo(m_handle); -} - -inline Subscriber::~Subscriber() { - ::nt::Release(m_subHandle); -} - -inline Subscriber::Subscriber(Subscriber&& rhs) : m_subHandle{rhs.m_subHandle} { - rhs.m_subHandle = 0; -} - -inline Subscriber& Subscriber::operator=(Subscriber&& rhs) { - if (m_subHandle != 0) { - ::nt::Release(m_subHandle); - } - m_subHandle = rhs.m_subHandle; - rhs.m_subHandle = 0; - return *this; -} - -inline bool Subscriber::Exists() const { - return nt::GetTopicExists(m_subHandle); -} - -inline int64_t Subscriber::GetLastChange() const { - return ::nt::GetEntryLastChange(m_subHandle); -} - -inline Topic Subscriber::GetTopic() const { - return Topic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -inline Publisher::~Publisher() { - ::nt::Release(m_pubHandle); -} - -inline Publisher::Publisher(Publisher&& rhs) : m_pubHandle{rhs.m_pubHandle} { - rhs.m_pubHandle = 0; -} - -inline Publisher& Publisher::operator=(Publisher&& rhs) { - if (m_pubHandle != 0) { - ::nt::Release(m_pubHandle); - } - m_pubHandle = rhs.m_pubHandle; - rhs.m_pubHandle = 0; - return *this; -} - -inline Topic Publisher::GetTopic() const { - return Topic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -} // namespace nt diff --git a/ntcore/src/main/native/include/networktables/UnitTopic.h b/ntcore/src/main/native/include/networktables/UnitTopic.h index eb6ad6dcad3..ff836c034a3 100644 --- a/ntcore/src/main/native/include/networktables/UnitTopic.h +++ b/ntcore/src/main/native/include/networktables/UnitTopic.h @@ -6,11 +6,10 @@ #include -#include #include #include -#include +#include #include "networktables/Topic.h" #include "ntcore_cpp.h" @@ -69,7 +68,8 @@ class UnitSubscriber : public Subscriber { * @param handle Native handle * @param defaultValue Default value */ - UnitSubscriber(NT_Subscriber handle, ParamType defaultValue); + UnitSubscriber(NT_Subscriber handle, ParamType defaultValue) + : Subscriber{handle}, m_defaultValue{defaultValue} {} /** * Get the last published value. @@ -77,7 +77,7 @@ class UnitSubscriber : public Subscriber { * * @return value */ - ValueType Get() const; + ValueType Get() const { return Get(m_defaultValue); } /** * Get the last published value. @@ -86,7 +86,9 @@ class UnitSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return value */ - ValueType Get(ParamType defaultValue) const; + ValueType Get(ParamType defaultValue) const { + return T{::nt::GetDouble(m_subHandle, defaultValue.value())}; + } /** * Get the last published value along with its timestamp @@ -95,7 +97,7 @@ class UnitSubscriber : public Subscriber { * * @return timestamped value */ - TimestampedValueType GetAtomic() const; + TimestampedValueType GetAtomic() const { return GetAtomic(m_defaultValue); } /** * Get the last published value along with its timestamp. @@ -105,7 +107,10 @@ class UnitSubscriber : public Subscriber { * @param defaultValue default value to return if no value has been published * @return timestamped value */ - TimestampedValueType GetAtomic(ParamType defaultValue) const; + TimestampedValueType GetAtomic(ParamType defaultValue) const { + auto doubleVal = ::nt::GetAtomicDouble(m_subHandle, defaultValue.value()); + return {doubleVal.time, doubleVal.serverTime, doubleVal.value}; + } /** * Get an array of all value changes since the last call to ReadQueue. @@ -117,14 +122,23 @@ class UnitSubscriber : public Subscriber { * @return Array of timestamped values; empty array if no new changes have * been published since the previous call. */ - std::vector ReadQueue(); + std::vector ReadQueue() { + std::vector> vals; + auto doubleVals = ::nt::ReadQueueDouble(m_subHandle); + vals.reserve(doubleVals.size()); + for (auto&& val : doubleVals) { + vals.emplace_back(val.time, val.serverTime, val.value); + } + } /** * Get the corresponding topic. * * @return Topic */ - TopicType GetTopic() const; + TopicType GetTopic() const { + return UnitTopic{::nt::GetTopicFromHandle(m_subHandle)}; + } private: ValueType m_defaultValue; @@ -152,7 +166,7 @@ class UnitPublisher : public Publisher { * * @param handle Native handle */ - explicit UnitPublisher(NT_Publisher handle); + explicit UnitPublisher(NT_Publisher handle) : Publisher{handle} {} /** * Publish a new value. @@ -160,7 +174,9 @@ class UnitPublisher : public Publisher { * @param value value to publish * @param time timestamp; 0 indicates current NT time should be used */ - void Set(ParamType value, int64_t time = 0); + void Set(ParamType value, int64_t time = 0) { + ::nt::SetDouble(m_pubHandle, value.value(), time); + } /** * Publish a default value. @@ -169,14 +185,18 @@ class UnitPublisher : public Publisher { * * @param value value */ - void SetDefault(ParamType value); + void SetDefault(ParamType value) { + ::nt::SetDefaultDouble(m_pubHandle, value.value()); + } /** * Get the corresponding topic. * * @return Topic */ - TopicType GetTopic() const; + TopicType GetTopic() const { + return UnitTopic{::nt::GetTopicFromHandle(m_pubHandle)}; + } }; /** @@ -206,7 +226,8 @@ class UnitEntry final : public UnitSubscriber, public UnitPublisher { * @param handle Native handle * @param defaultValue Default value */ - UnitEntry(NT_Entry handle, ParamType defaultValue); + UnitEntry(NT_Entry handle, ParamType defaultValue) + : UnitSubscriber{handle, defaultValue}, UnitPublisher{handle} {} /** * Determines if the native handle is valid. @@ -227,12 +248,14 @@ class UnitEntry final : public UnitSubscriber, public UnitPublisher { * * @return Topic */ - TopicType GetTopic() const; + TopicType GetTopic() const { + return UnitTopic{::nt::GetTopicFromHandle(this->m_subHandle)}; + } /** * Stops publishing the entry if it's published. */ - void Unpublish(); + void Unpublish() { ::nt::Unpublish(this->m_pubHandle); } }; /** @@ -276,7 +299,7 @@ class UnitTopic final : public Topic { * * @return True if unit matches, false if not matching or topic not published. */ - bool IsMatchingUnit() const; + bool IsMatchingUnit() const { return GetProperty("unit") == T{}.name(); } /** * Create a new subscriber to the topic. @@ -296,7 +319,10 @@ class UnitTopic final : public Topic { [[nodiscard]] SubscriberType Subscribe( ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return UnitSubscriber{ + ::nt::Subscribe(m_handle, NT_DOUBLE, "double", options), defaultValue}; + } /** * Create a new subscriber to the topic, with specific type string. @@ -317,7 +343,11 @@ class UnitTopic final : public Topic { [[nodiscard]] SubscriberType SubscribeEx( std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return UnitSubscriber{ + ::nt::Subscribe(m_handle, NT_DOUBLE, typeString, options), + defaultValue}; + } /** * Create a new publisher to the topic. @@ -335,7 +365,10 @@ class UnitTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return UnitPublisher{::nt::PublishEx(m_handle, NT_DOUBLE, "double", + {{"unit", T{}.name()}}, options)}; + } /** * Create a new publisher to the topic, with type string and initial @@ -356,9 +389,14 @@ class UnitTopic final : public Topic { * @return publisher */ [[nodiscard]] - PublisherType PublishEx(std::string_view typeString, - const wpi::json& properties, - const PubSubOptions& options = kDefaultPubSubOptions); + PublisherType PublishEx( + std::string_view typeString, const wpi::json& properties, + const PubSubOptions& options = kDefaultPubSubOptions) { + wpi::json props = properties; + props["unit"] = T{}.name(); + return UnitPublisher{ + ::nt::PublishEx(m_handle, NT_DOUBLE, typeString, props, options)}; + } /** * Create a new entry for the topic. @@ -382,7 +420,10 @@ class UnitTopic final : public Topic { */ [[nodiscard]] EntryType GetEntry(ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return UnitEntry{::nt::GetEntry(m_handle, NT_DOUBLE, "double", options), + defaultValue}; + } /** * Create a new entry for the topic, with specific type string. @@ -407,9 +448,10 @@ class UnitTopic final : public Topic { */ [[nodiscard]] EntryType GetEntryEx(std::string_view typeString, ParamType defaultValue, - const PubSubOptions& options = kDefaultPubSubOptions); + const PubSubOptions& options = kDefaultPubSubOptions) { + return UnitEntry{ + ::nt::GetEntry(m_handle, NT_DOUBLE, typeString, options), defaultValue}; + } }; } // namespace nt - -#include "networktables/UnitTopic.inc" diff --git a/ntcore/src/main/native/include/networktables/UnitTopic.inc b/ntcore/src/main/native/include/networktables/UnitTopic.inc deleted file mode 100644 index c107526da1f..00000000000 --- a/ntcore/src/main/native/include/networktables/UnitTopic.inc +++ /dev/null @@ -1,140 +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 - -#include - -#include "networktables/NetworkTableType.h" -#include "networktables/UnitTopic.h" -#include "ntcore_cpp.h" - -namespace nt { - -template -inline UnitSubscriber::UnitSubscriber(NT_Subscriber handle, T defaultValue) - : Subscriber{handle}, m_defaultValue{defaultValue} {} - -template -inline T UnitSubscriber::Get() const { - return Get(m_defaultValue); -} - -template -inline T UnitSubscriber::Get(T defaultValue) const { - return T{::nt::GetDouble(m_subHandle, defaultValue.value())}; -} - -template -inline TimestampedUnit UnitSubscriber::GetAtomic() const { - return GetAtomic(m_defaultValue); -} - -template -inline TimestampedUnit UnitSubscriber::GetAtomic(T defaultValue) const { - auto doubleVal = ::nt::GetAtomicDouble(m_subHandle, defaultValue.value()); - return {doubleVal.time, doubleVal.serverTime, doubleVal.value}; -} - -template -inline std::vector> UnitSubscriber::ReadQueue() { - std::vector> vals; - auto doubleVals = ::nt::ReadQueueDouble(m_subHandle); - vals.reserve(doubleVals.size()); - for (auto&& val : doubleVals) { - vals.emplace_back(val.time, val.serverTime, val.value); - } -} - -template -inline UnitTopic UnitSubscriber::GetTopic() const { - return UnitTopic{::nt::GetTopicFromHandle(m_subHandle)}; -} - -template -inline UnitPublisher::UnitPublisher(NT_Publisher handle) - : Publisher{handle} {} - -template -inline void UnitPublisher::Set(T value, int64_t time) { - ::nt::SetDouble(m_pubHandle, value.value(), time); -} - -template -inline void UnitPublisher::SetDefault(T value) { - ::nt::SetDefaultDouble(m_pubHandle, value.value()); -} - -template -inline UnitTopic UnitPublisher::GetTopic() const { - return UnitTopic{::nt::GetTopicFromHandle(m_pubHandle)}; -} - -template -inline UnitEntry::UnitEntry(NT_Entry handle, T defaultValue) - : UnitSubscriber{handle, defaultValue}, UnitPublisher{handle} {} - -template -inline UnitTopic UnitEntry::GetTopic() const { - return UnitTopic{::nt::GetTopicFromHandle(this->m_subHandle)}; -} - -template -inline void UnitEntry::Unpublish() { - ::nt::Unpublish(this->m_pubHandle); -} - -template -inline bool UnitTopic::IsMatchingUnit() const { - return GetProperty("unit") == T{}.name(); -} - -template -inline UnitSubscriber UnitTopic::Subscribe(T defaultValue, - const PubSubOptions& options) { - return UnitSubscriber{ - ::nt::Subscribe(m_handle, NT_DOUBLE, "double", options), defaultValue}; -} - -template -inline UnitSubscriber UnitTopic::SubscribeEx( - std::string_view typeString, T defaultValue, const PubSubOptions& options) { - return UnitSubscriber{ - ::nt::Subscribe(m_handle, NT_DOUBLE, typeString, options), defaultValue}; -} - -template -inline UnitPublisher UnitTopic::Publish(const PubSubOptions& options) { - return UnitPublisher{::nt::PublishEx(m_handle, NT_DOUBLE, "double", - {{"unit", T{}.name()}}, options)}; -} - -template -inline UnitPublisher UnitTopic::PublishEx(std::string_view typeString, - const wpi::json& properties, - const PubSubOptions& options) { - wpi::json props = properties; - props["unit"] = T{}.name(); - return UnitPublisher{ - ::nt::PublishEx(m_handle, NT_DOUBLE, typeString, props, options)}; -} - -template -inline UnitEntry UnitTopic::GetEntry(T defaultValue, - const PubSubOptions& options) { - return UnitEntry{::nt::GetEntry(m_handle, NT_DOUBLE, "double", options), - defaultValue}; -} - -template -inline UnitEntry UnitTopic::GetEntryEx(std::string_view typeString, - T defaultValue, - const PubSubOptions& options) { - return UnitEntry{::nt::GetEntry(m_handle, NT_DOUBLE, typeString, options), - defaultValue}; -} - -} // namespace nt diff --git a/ntcoreffi/src/main/native/symbols.txt b/ntcoreffi/src/main/native/symbols.txt index 15668d45773..906da957f83 100644 --- a/ntcoreffi/src/main/native/symbols.txt +++ b/ntcoreffi/src/main/native/symbols.txt @@ -14,6 +14,7 @@ NT_AddPolledListener NT_AddPolledListenerMultiple NT_AddPolledListenerSingle NT_AddPolledLogger +NT_AddSchema NT_AllocateBooleanArray NT_AllocateCharArray NT_AllocateDoubleArray @@ -24,6 +25,7 @@ NT_CreateListenerPoller NT_DeleteTopicProperty NT_DestroyInstance NT_DestroyListenerPoller +NT_Disconnect NT_DisposeConnectionInfoArray NT_DisposeEvent NT_DisposeEventArray @@ -87,6 +89,7 @@ NT_GetEntryLastChange NT_GetEntryName NT_GetEntryType NT_GetEntryValue +NT_GetEntryValueType NT_GetFloat NT_GetFloatArray NT_GetInstanceFromHandle @@ -99,6 +102,7 @@ NT_GetString NT_GetStringArray NT_GetStringForTesting NT_GetTopic +NT_GetTopicCached NT_GetTopicExists NT_GetTopicFromHandle NT_GetTopicInfo @@ -133,22 +137,17 @@ NT_GetValueStringArray NT_GetValueStringArrayForTesting NT_GetValueStringForTesting NT_GetValueType -WPI_InitString -WPI_InitStringWithLength -WPI_AllocateString -WPI_FreeString -WPI_AllocateStringArray -WPI_FreeStringArray +NT_HasSchema NT_InitValue NT_IsConnected NT_Meta_DecodeClientPublishers -NT_Meta_DecodeClientSubscribers NT_Meta_DecodeClients +NT_Meta_DecodeClientSubscribers NT_Meta_DecodeTopicPublishers NT_Meta_DecodeTopicSubscribers NT_Meta_FreeClientPublishers -NT_Meta_FreeClientSubscribers NT_Meta_FreeClients +NT_Meta_FreeClientSubscribers NT_Meta_FreeTopicPublishers NT_Meta_FreeTopicSubscribers NT_Now @@ -171,6 +170,7 @@ NT_ReadQueueValuesBoolean NT_ReadQueueValuesDouble NT_ReadQueueValuesFloat NT_ReadQueueValuesInteger +NT_ReadQueueValueType NT_Release NT_ReleaseEntry NT_RemoveListener @@ -203,6 +203,7 @@ NT_SetServerMulti NT_SetServerTeam NT_SetString NT_SetStringArray +NT_SetTopicCached NT_SetTopicPersistent NT_SetTopicProperties NT_SetTopicProperty @@ -221,9 +222,13 @@ NT_StopEntryDataLog NT_StopLocal NT_StopServer NT_Subscribe +NT_SubscribeMultiple NT_Unpublish NT_Unsubscribe +NT_UnsubscribeMultiple NT_WaitForListenerQueue +WPI_AllocateString +WPI_AllocateStringArray WPI_CreateEvent WPI_CreateSemaphore WPI_CreateSignalObject @@ -254,10 +259,14 @@ WPI_DataLog_Stop WPI_DestroyEvent WPI_DestroySemaphore WPI_DestroySignalObject +WPI_FreeString +WPI_FreeStringArray WPI_GetSystemTime WPI_Impl_SetupNowUseDefaultOnRio WPI_Impl_SetupNowRioWithSession WPI_Impl_ShutdownNowRio +WPI_InitString +WPI_InitStringWithLength WPI_Now WPI_NowDefault WPI_ReleaseSemaphore diff --git a/simulation/halsim_ws_core/src/main/native/include/WSHalProviders.h b/simulation/halsim_ws_core/src/main/native/include/WSHalProviders.h index 849edebc08c..adf6135eb1c 100644 --- a/simulation/halsim_ws_core/src/main/native/include/WSHalProviders.h +++ b/simulation/halsim_ws_core/src/main/native/include/WSHalProviders.h @@ -6,9 +6,10 @@ #include #include -#include #include +#include +#include #include #include #include @@ -56,11 +57,19 @@ using WSRegisterFunc = std::function 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(i, key, prefix); + webRegisterFunc(key, std::move(ptr)); + } +} template -void CreateSingleProvider(std::string_view key, WSRegisterFunc webRegisterFunc); +void CreateSingleProvider(std::string_view key, + WSRegisterFunc webRegisterFunc) { + auto ptr = std::make_unique(key, key); + webRegisterFunc(key, std::move(ptr)); +} } // namespace wpilibws - -#include "WSHalProviders.inc" diff --git a/simulation/halsim_ws_core/src/main/native/include/WSHalProviders.inc b/simulation/halsim_ws_core/src/main/native/include/WSHalProviders.inc deleted file mode 100644 index c9ce9d14d83..00000000000 --- a/simulation/halsim_ws_core/src/main/native/include/WSHalProviders.inc +++ /dev/null @@ -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 -#include -#include - -#include - -#include "WSHalProviders.h" - -namespace wpilibws { - -template -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(i, key, prefix); - webRegisterFunc(key, std::move(ptr)); - } -} - -template -void CreateSingleProvider(std::string_view key, - WSRegisterFunc webRegisterFunc) { - auto ptr = std::make_unique(key, key); - webRegisterFunc(key, std::move(ptr)); -} - -} // namespace wpilibws diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/SwerveControllerCommand.h b/wpilibNewCommands/src/main/native/include/frc2/command/SwerveControllerCommand.h index 388730f89c3..75205e99289 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/SwerveControllerCommand.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/SwerveControllerCommand.h @@ -3,6 +3,8 @@ // the WPILib BSD license file in the root directory of this project. #include +#include +#include #include #include @@ -91,7 +93,15 @@ class SwerveControllerCommand std::function desiredRotation, std::function)> 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 thetaController, std::function)> 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 desiredRotation, std::function)> 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)> 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 diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/SwerveControllerCommand.inc b/wpilibNewCommands/src/main/native/include/frc2/command/SwerveControllerCommand.inc deleted file mode 100644 index d0c34af2b72..00000000000 --- a/wpilibNewCommands/src/main/native/include/frc2/command/SwerveControllerCommand.inc +++ /dev/null @@ -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 -#include -#include - -#include "frc2/command/SwerveControllerCommand.h" - -namespace frc2 { - -template -SwerveControllerCommand::SwerveControllerCommand( - frc::Trajectory trajectory, std::function pose, - frc::SwerveDriveKinematics kinematics, - frc::PIDController xController, frc::PIDController yController, - frc::ProfiledPIDController thetaController, - std::function desiredRotation, - std::function)> 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 -SwerveControllerCommand::SwerveControllerCommand( - frc::Trajectory trajectory, std::function pose, - frc::SwerveDriveKinematics kinematics, - frc::PIDController xController, frc::PIDController yController, - frc::ProfiledPIDController thetaController, - std::function)> 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 -SwerveControllerCommand::SwerveControllerCommand( - frc::Trajectory trajectory, std::function pose, - frc::SwerveDriveKinematics kinematics, - frc::HolonomicDriveController controller, - std::function desiredRotation, - std::function)> 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 -SwerveControllerCommand::SwerveControllerCommand( - frc::Trajectory trajectory, std::function pose, - frc::SwerveDriveKinematics kinematics, - frc::HolonomicDriveController controller, - std::function)> 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 -void SwerveControllerCommand::Initialize() { - if (m_desiredRotation == nullptr) { - m_desiredRotation = [&] { - return m_trajectory.States().back().pose.Rotation(); - }; - } - m_timer.Restart(); -} - -template -void SwerveControllerCommand::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 -void SwerveControllerCommand::End(bool interrupted) { - m_timer.Stop(); -} - -template -bool SwerveControllerCommand::IsFinished() { - return m_timer.HasElapsed(m_trajectory.TotalTime()); -} - -} // namespace frc2 diff --git a/wpilibc/src/main/native/cpp/Counter.cpp b/wpilibc/src/main/native/cpp/Counter.cpp index 1c35923969a..32523c245a2 100644 --- a/wpilibc/src/main/native/cpp/Counter.cpp +++ b/wpilibc/src/main/native/cpp/Counter.cpp @@ -84,10 +84,12 @@ Counter::Counter(EncodingType encodingType, } Counter::~Counter() { - try { - SetUpdateWhenEmpty(true); - } catch (const RuntimeError& e) { - e.Report(); + if (m_counter != HAL_kInvalidHandle) { + try { + SetUpdateWhenEmpty(true); + } catch (const RuntimeError& e) { + e.Report(); + } } } diff --git a/wpilibc/src/main/native/cpp/DigitalOutput.cpp b/wpilibc/src/main/native/cpp/DigitalOutput.cpp index bfcd2dc7dca..ee54bb4294d 100644 --- a/wpilibc/src/main/native/cpp/DigitalOutput.cpp +++ b/wpilibc/src/main/native/cpp/DigitalOutput.cpp @@ -37,11 +37,13 @@ DigitalOutput::DigitalOutput(int channel) { } DigitalOutput::~DigitalOutput() { - // Disable the PWM in case it was running. - try { - DisablePWM(); - } catch (const RuntimeError& e) { - e.Report(); + if (m_handle != HAL_kInvalidHandle) { + // Disable the PWM in case it was running. + try { + DisablePWM(); + } catch (const RuntimeError& e) { + e.Report(); + } } } diff --git a/wpilibc/src/main/native/cpp/PWM.cpp b/wpilibc/src/main/native/cpp/PWM.cpp index c9d77d45113..f623ba40ff9 100644 --- a/wpilibc/src/main/native/cpp/PWM.cpp +++ b/wpilibc/src/main/native/cpp/PWM.cpp @@ -45,9 +45,11 @@ PWM::PWM(int channel, bool registerSendable) { } PWM::~PWM() { - int32_t status = 0; - HAL_SetPWMDisabled(m_handle, &status); - FRC_ReportError(status, "Channel {}", m_channel); + if (m_handle != HAL_kInvalidHandle) { + int32_t status = 0; + HAL_SetPWMDisabled(m_handle, &status); + FRC_ReportError(status, "Channel {}", m_channel); + } } void PWM::SetPulseTime(units::microsecond_t time) { diff --git a/wpilibc/src/main/native/cpp/Relay.cpp b/wpilibc/src/main/native/cpp/Relay.cpp index 0cd2dac86b1..c3cc70c2bc5 100644 --- a/wpilibc/src/main/native/cpp/Relay.cpp +++ b/wpilibc/src/main/native/cpp/Relay.cpp @@ -61,8 +61,12 @@ Relay::Relay(int channel, Relay::Direction direction) Relay::~Relay() { int32_t status = 0; - HAL_SetRelay(m_forwardHandle, false, &status); - HAL_SetRelay(m_reverseHandle, false, &status); + if (m_forwardHandle != HAL_kInvalidHandle) { + HAL_SetRelay(m_forwardHandle, false, &status); + } + if (m_reverseHandle != HAL_kInvalidHandle) { + HAL_SetRelay(m_reverseHandle, false, &status); + } } void Relay::Set(Relay::Value value) { diff --git a/wpilibc/src/main/native/cpp/TimedRobot.cpp b/wpilibc/src/main/native/cpp/TimedRobot.cpp index 4b0ebff3424..7ff22a9f347 100644 --- a/wpilibc/src/main/native/cpp/TimedRobot.cpp +++ b/wpilibc/src/main/native/cpp/TimedRobot.cpp @@ -90,10 +90,11 @@ TimedRobot::TimedRobot(units::second_t period) : IterativeRobotBase(period) { } TimedRobot::~TimedRobot() { - int32_t status = 0; - - HAL_StopNotifier(m_notifier, &status); - FRC_ReportError(status, "StopNotifier"); + if (m_notifier != HAL_kInvalidHandle) { + int32_t status = 0; + HAL_StopNotifier(m_notifier, &status); + FRC_ReportError(status, "StopNotifier"); + } } void TimedRobot::AddPeriodic(std::function callback, diff --git a/wpilibc/src/main/native/include/frc/motorcontrol/MotorControllerGroup.h b/wpilibc/src/main/native/include/frc/motorcontrol/MotorControllerGroup.h index 6500fb3e2f0..532fecde7f5 100644 --- a/wpilibc/src/main/native/include/frc/motorcontrol/MotorControllerGroup.h +++ b/wpilibc/src/main/native/include/frc/motorcontrol/MotorControllerGroup.h @@ -36,7 +36,11 @@ class [[deprecated( */ template explicit MotorControllerGroup(MotorController& motorController, - MotorControllers&... motorControllers); + MotorControllers&... motorControllers) + : m_motorControllers(std::vector>{ + 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 diff --git a/wpilibc/src/main/native/include/frc/motorcontrol/MotorControllerGroup.inc b/wpilibc/src/main/native/include/frc/motorcontrol/MotorControllerGroup.inc deleted file mode 100644 index 8f876354a19..00000000000 --- a/wpilibc/src/main/native/include/frc/motorcontrol/MotorControllerGroup.inc +++ /dev/null @@ -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 -#include - -#include "frc/motorcontrol/MotorControllerGroup.h" - -namespace frc { - -template -MotorControllerGroup::MotorControllerGroup( - MotorController& motorController, MotorControllers&... motorControllers) - : m_motorControllers(std::vector>{ - motorController, motorControllers...}) { - Initialize(); -} - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h index 8cb867388bc..3441c5784df 100644 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h +++ b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h @@ -4,8 +4,6 @@ #pragma once -#include -#include #include #include @@ -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& properties); + Derived& WithProperties(const wpi::StringMap& properties) { + m_properties = properties; + m_metadataDirty = true; + return *static_cast(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(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(this); + } }; } // namespace frc - -#include "frc/shuffleboard/ShuffleboardComponent.inc" diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.inc b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.inc deleted file mode 100644 index 63a4933181e..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.inc +++ /dev/null @@ -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 -#include -#include - -#include "frc/shuffleboard/ShuffleboardComponent.h" - -namespace frc { - -template -ShuffleboardComponent::ShuffleboardComponent( - ShuffleboardContainer& parent, std::string_view title, - std::string_view type) - : ShuffleboardValue(title), - ShuffleboardComponentBase(parent, title, type) {} - -template -Derived& ShuffleboardComponent::WithProperties( - const wpi::StringMap& properties) { - m_properties = properties; - m_metadataDirty = true; - return *static_cast(this); -} - -template -Derived& ShuffleboardComponent::WithPosition(int columnIndex, - int rowIndex) { - m_column = columnIndex; - m_row = rowIndex; - m_metadataDirty = true; - return *static_cast(this); -} - -template -Derived& ShuffleboardComponent::WithSize(int width, int height) { - m_width = width; - m_height = height; - m_metadataDirty = true; - return *static_cast(this); -} - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h index 4f82dc61196..c044f25d351 100644 --- a/wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h +++ b/wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h @@ -14,7 +14,6 @@ #include #include "frc/shuffleboard/ShuffleboardComponent.h" -#include "frc/shuffleboard/ShuffleboardComponent.inc" #include "frc/shuffleboard/ShuffleboardComponentBase.h" #include "frc/shuffleboard/ShuffleboardWidget.h" diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h index 0c17fdefe96..3cf022ba126 100644 --- a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h +++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.h @@ -4,12 +4,17 @@ #pragma once +#include #include #include #include +#include #include +#include +#include #include +#include #include "frc/smartdashboard/SendableChooserBase.h" @@ -34,10 +39,14 @@ class SendableChooser : public SendableChooserBase { wpi::StringMap m_choices; std::function m_listener; template - static U _unwrap_smart_ptr(const U& value); + static U _unwrap_smart_ptr(const U& value) { + return value; + } template - static std::weak_ptr _unwrap_smart_ptr(const std::shared_ptr& value); + static std::weak_ptr _unwrap_smart_ptr(const std::shared_ptr& 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 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 InitSendable(wpi::SendableBuilder& builder) override; + void OnChange(std::function listener) { + std::scoped_lock lock(m_mutex); + m_listener = listener; + } + + void InitSendable(wpi::SendableBuilder& builder) override { + builder.SetSmartDashboardType("String Chooser"); + builder.PublishConstInteger(kInstance, m_instance); + builder.AddStringArrayProperty( + kOptions, + [=, this] { + std::vector 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&) -> std::string_view { + return m_defaultChoice; + }, + nullptr); + builder.AddSmallStringProperty( + kActive, + [=, this](wpi::SmallVectorImpl& 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 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" diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.inc b/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.inc deleted file mode 100644 index 2b93629959c..00000000000 --- a/wpilibc/src/main/native/include/frc/smartdashboard/SendableChooser.inc +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include - -#include - -#include "frc/smartdashboard/SendableChooser.h" - -namespace frc { - -template - requires std::copy_constructible && std::default_initializable -void SendableChooser::AddOption(std::string_view name, T object) { - m_choices[name] = std::move(object); -} - -template - requires std::copy_constructible && std::default_initializable -void SendableChooser::SetDefaultOption(std::string_view name, T object) { - m_defaultChoice = name; - AddOption(name, std::move(object)); -} - -template - requires std::copy_constructible && std::default_initializable -typename SendableChooser::CopyType SendableChooser::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 - requires std::copy_constructible && std::default_initializable -void SendableChooser::OnChange(std::function listener) { - std::scoped_lock lock(m_mutex); - m_listener = listener; -} - -template - requires std::copy_constructible && std::default_initializable -void SendableChooser::InitSendable(wpi::SendableBuilder& builder) { - builder.SetSmartDashboardType("String Chooser"); - builder.PublishConstInteger(kInstance, m_instance); - builder.AddStringArrayProperty( - kOptions, - [=, this] { - std::vector 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&) -> std::string_view { - return m_defaultChoice; - }, - nullptr); - builder.AddSmallStringProperty( - kActive, - [=, this](wpi::SmallVectorImpl& 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 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 - requires std::copy_constructible && std::default_initializable -template -U SendableChooser::_unwrap_smart_ptr(const U& value) { - return value; -} - -template - requires std::copy_constructible && std::default_initializable -template -std::weak_ptr SendableChooser::_unwrap_smart_ptr( - const std::shared_ptr& value) { - return value; -} - -} // namespace frc diff --git a/wpilibcExamples/src/main/cpp/examples/SysId/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/examples/SysIdRoutine/cpp/Robot.cpp similarity index 100% rename from wpilibcExamples/src/main/cpp/examples/SysId/cpp/Robot.cpp rename to wpilibcExamples/src/main/cpp/examples/SysIdRoutine/cpp/Robot.cpp diff --git a/wpilibcExamples/src/main/cpp/examples/SysId/cpp/SysIdRoutineBot.cpp b/wpilibcExamples/src/main/cpp/examples/SysIdRoutine/cpp/SysIdRoutineBot.cpp similarity index 100% rename from wpilibcExamples/src/main/cpp/examples/SysId/cpp/SysIdRoutineBot.cpp rename to wpilibcExamples/src/main/cpp/examples/SysIdRoutine/cpp/SysIdRoutineBot.cpp diff --git a/wpilibcExamples/src/main/cpp/examples/SysId/cpp/subsystems/Drive.cpp b/wpilibcExamples/src/main/cpp/examples/SysIdRoutine/cpp/subsystems/Drive.cpp similarity index 100% rename from wpilibcExamples/src/main/cpp/examples/SysId/cpp/subsystems/Drive.cpp rename to wpilibcExamples/src/main/cpp/examples/SysIdRoutine/cpp/subsystems/Drive.cpp diff --git a/wpilibcExamples/src/main/cpp/examples/SysId/cpp/subsystems/Shooter.cpp b/wpilibcExamples/src/main/cpp/examples/SysIdRoutine/cpp/subsystems/Shooter.cpp similarity index 100% rename from wpilibcExamples/src/main/cpp/examples/SysId/cpp/subsystems/Shooter.cpp rename to wpilibcExamples/src/main/cpp/examples/SysIdRoutine/cpp/subsystems/Shooter.cpp diff --git a/wpilibcExamples/src/main/cpp/examples/SysId/include/Constants.h b/wpilibcExamples/src/main/cpp/examples/SysIdRoutine/include/Constants.h similarity index 100% rename from wpilibcExamples/src/main/cpp/examples/SysId/include/Constants.h rename to wpilibcExamples/src/main/cpp/examples/SysIdRoutine/include/Constants.h diff --git a/wpilibcExamples/src/main/cpp/examples/SysId/include/Robot.h b/wpilibcExamples/src/main/cpp/examples/SysIdRoutine/include/Robot.h similarity index 100% rename from wpilibcExamples/src/main/cpp/examples/SysId/include/Robot.h rename to wpilibcExamples/src/main/cpp/examples/SysIdRoutine/include/Robot.h diff --git a/wpilibcExamples/src/main/cpp/examples/SysId/include/SysIdRoutineBot.h b/wpilibcExamples/src/main/cpp/examples/SysIdRoutine/include/SysIdRoutineBot.h similarity index 100% rename from wpilibcExamples/src/main/cpp/examples/SysId/include/SysIdRoutineBot.h rename to wpilibcExamples/src/main/cpp/examples/SysIdRoutine/include/SysIdRoutineBot.h diff --git a/wpilibcExamples/src/main/cpp/examples/SysId/include/subsystems/Drive.h b/wpilibcExamples/src/main/cpp/examples/SysIdRoutine/include/subsystems/Drive.h similarity index 100% rename from wpilibcExamples/src/main/cpp/examples/SysId/include/subsystems/Drive.h rename to wpilibcExamples/src/main/cpp/examples/SysIdRoutine/include/subsystems/Drive.h diff --git a/wpilibcExamples/src/main/cpp/examples/SysId/include/subsystems/Shooter.h b/wpilibcExamples/src/main/cpp/examples/SysIdRoutine/include/subsystems/Shooter.h similarity index 100% rename from wpilibcExamples/src/main/cpp/examples/SysId/include/subsystems/Shooter.h rename to wpilibcExamples/src/main/cpp/examples/SysIdRoutine/include/subsystems/Shooter.h diff --git a/wpilibcExamples/src/main/cpp/examples/examples.json b/wpilibcExamples/src/main/cpp/examples/examples.json index ef53f478c0e..ea40670bb0e 100644 --- a/wpilibcExamples/src/main/cpp/examples/examples.json +++ b/wpilibcExamples/src/main/cpp/examples/examples.json @@ -809,7 +809,7 @@ "Command-based", "DataLog" ], - "foldername": "SysId", + "foldername": "SysIdRoutine", "gradlebase": "cpp", "commandversion": 2 } diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json index 8a108ac3540..3ed52e1bef9 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json @@ -857,7 +857,7 @@ "Command-based", "DataLog" ], - "foldername": "sysid", + "foldername": "sysidroutine", "gradlebase": "java", "commandversion": 2, "mainclass": "Main" diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/Constants.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/Constants.java similarity index 98% rename from wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/Constants.java rename to wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/Constants.java index a6f09eb2d92..7e45d022479 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/Constants.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/Constants.java @@ -2,7 +2,7 @@ // 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. -package edu.wpi.first.wpilibj.examples.sysid; +package edu.wpi.first.wpilibj.examples.sysidroutine; import edu.wpi.first.math.util.Units; diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/Main.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/Main.java similarity index 93% rename from wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/Main.java rename to wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/Main.java index 1fdd4b7374c..8c9ee5ed134 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/Main.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/Main.java @@ -2,7 +2,7 @@ // 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. -package edu.wpi.first.wpilibj.examples.sysid; +package edu.wpi.first.wpilibj.examples.sysidroutine; import edu.wpi.first.wpilibj.RobotBase; diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/Robot.java similarity index 98% rename from wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/Robot.java rename to wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/Robot.java index 3f9640ffed9..fcf7e60473f 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/Robot.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/Robot.java @@ -2,7 +2,7 @@ // 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. -package edu.wpi.first.wpilibj.examples.sysid; +package edu.wpi.first.wpilibj.examples.sysidroutine; import edu.wpi.first.wpilibj.TimedRobot; import edu.wpi.first.wpilibj2.command.Command; diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/SysIdRoutineBot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/SysIdRoutineBot.java similarity index 93% rename from wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/SysIdRoutineBot.java rename to wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/SysIdRoutineBot.java index 7537c0bf937..acaa1579a26 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/SysIdRoutineBot.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/SysIdRoutineBot.java @@ -2,11 +2,11 @@ // 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. -package edu.wpi.first.wpilibj.examples.sysid; +package edu.wpi.first.wpilibj.examples.sysidroutine; -import edu.wpi.first.wpilibj.examples.sysid.Constants.OIConstants; -import edu.wpi.first.wpilibj.examples.sysid.subsystems.Drive; -import edu.wpi.first.wpilibj.examples.sysid.subsystems.Shooter; +import edu.wpi.first.wpilibj.examples.sysidroutine.Constants.OIConstants; +import edu.wpi.first.wpilibj.examples.sysidroutine.subsystems.Drive; +import edu.wpi.first.wpilibj.examples.sysidroutine.subsystems.Shooter; import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.button.CommandXboxController; import edu.wpi.first.wpilibj2.command.button.Trigger; diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/subsystems/Drive.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/subsystems/Drive.java similarity index 97% rename from wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/subsystems/Drive.java rename to wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/subsystems/Drive.java index ae1b1aa37f3..490b38acab2 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/subsystems/Drive.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/subsystems/Drive.java @@ -2,7 +2,7 @@ // 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. -package edu.wpi.first.wpilibj.examples.sysid.subsystems; +package edu.wpi.first.wpilibj.examples.sysidroutine.subsystems; import static edu.wpi.first.units.Units.Meters; import static edu.wpi.first.units.Units.MetersPerSecond; @@ -14,7 +14,7 @@ import edu.wpi.first.wpilibj.Encoder; import edu.wpi.first.wpilibj.RobotController; import edu.wpi.first.wpilibj.drive.DifferentialDrive; -import edu.wpi.first.wpilibj.examples.sysid.Constants.DriveConstants; +import edu.wpi.first.wpilibj.examples.sysidroutine.Constants.DriveConstants; import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax; import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.SubsystemBase; diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/subsystems/Shooter.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/subsystems/Shooter.java similarity index 97% rename from wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/subsystems/Shooter.java rename to wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/subsystems/Shooter.java index 2b62f5c8064..cc7fbac2fe4 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysid/subsystems/Shooter.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/sysidroutine/subsystems/Shooter.java @@ -2,7 +2,7 @@ // 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. -package edu.wpi.first.wpilibj.examples.sysid.subsystems; +package edu.wpi.first.wpilibj.examples.sysidroutine.subsystems; import static edu.wpi.first.units.Units.Radians; import static edu.wpi.first.units.Units.RadiansPerSecond; @@ -17,7 +17,7 @@ import edu.wpi.first.units.measure.MutVoltage; import edu.wpi.first.wpilibj.Encoder; import edu.wpi.first.wpilibj.RobotController; -import edu.wpi.first.wpilibj.examples.sysid.Constants.ShooterConstants; +import edu.wpi.first.wpilibj.examples.sysidroutine.Constants.ShooterConstants; import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax; import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.SubsystemBase; diff --git a/wpimath/src/main/native/cpp/geometry/Translation3d.cpp b/wpimath/src/main/native/cpp/geometry/Translation3d.cpp index 69757f30801..1609f434e8b 100644 --- a/wpimath/src/main/native/cpp/geometry/Translation3d.cpp +++ b/wpimath/src/main/native/cpp/geometry/Translation3d.cpp @@ -6,46 +6,8 @@ #include -#include "units/length.h" -#include "units/math.h" - using namespace frc; -Translation3d::Translation3d(units::meter_t distance, const Rotation3d& angle) { - auto rectangular = Translation3d{distance, 0_m, 0_m}.RotateBy(angle); - m_x = rectangular.X(); - m_y = rectangular.Y(); - m_z = rectangular.Z(); -} - -Translation3d::Translation3d(const Eigen::Vector3d& vector) - : m_x{units::meter_t{vector.x()}}, - m_y{units::meter_t{vector.y()}}, - m_z{units::meter_t{vector.z()}} {} - -units::meter_t Translation3d::Distance(const Translation3d& other) const { - return units::math::sqrt(units::math::pow<2>(other.m_x - m_x) + - units::math::pow<2>(other.m_y - m_y) + - units::math::pow<2>(other.m_z - m_z)); -} - -units::meter_t Translation3d::Norm() const { - return units::math::sqrt(m_x * m_x + m_y * m_y + m_z * m_z); -} - -Translation3d Translation3d::RotateBy(const Rotation3d& other) const { - Quaternion p{0.0, m_x.value(), m_y.value(), m_z.value()}; - auto qprime = other.GetQuaternion() * p * other.GetQuaternion().Inverse(); - return Translation3d{units::meter_t{qprime.X()}, units::meter_t{qprime.Y()}, - units::meter_t{qprime.Z()}}; -} - -bool Translation3d::operator==(const Translation3d& other) const { - return units::math::abs(m_x - other.m_x) < 1E-9_m && - units::math::abs(m_y - other.m_y) < 1E-9_m && - units::math::abs(m_z - other.m_z) < 1E-9_m; -} - void frc::to_json(wpi::json& json, const Translation3d& translation) { json = wpi::json{{"x", translation.X().value()}, {"y", translation.Y().value()}, diff --git a/wpimath/src/main/native/include/frc/controller/LinearQuadraticRegulator.h b/wpimath/src/main/native/include/frc/controller/LinearQuadraticRegulator.h index 2671b3dccb8..263a2a769ed 100644 --- a/wpimath/src/main/native/include/frc/controller/LinearQuadraticRegulator.h +++ b/wpimath/src/main/native/include/frc/controller/LinearQuadraticRegulator.h @@ -4,12 +4,22 @@ #pragma once +#include +#include + +#include +#include #include #include +#include "frc/DARE.h" #include "frc/EigenCore.h" +#include "frc/StateSpaceUtil.h" +#include "frc/fmt/Eigen.h" +#include "frc/system/Discretization.h" #include "frc/system/LinearSystem.h" #include "units/time.h" +#include "wpimath/MathShared.h" namespace frc { @@ -50,7 +60,8 @@ class LinearQuadraticRegulator { template LinearQuadraticRegulator(const LinearSystem& plant, const StateArray& Qelems, const InputArray& Relems, - units::second_t dt); + units::second_t dt) + : LinearQuadraticRegulator(plant.A(), plant.B(), Qelems, Relems, dt) {} /** * Constructs a controller with the given coefficients and plant. @@ -69,7 +80,9 @@ class LinearQuadraticRegulator { LinearQuadraticRegulator(const Matrixd& A, const Matrixd& B, const StateArray& Qelems, const InputArray& Relems, - units::second_t dt); + units::second_t dt) + : LinearQuadraticRegulator(A, B, MakeCostMatrix(Qelems), + MakeCostMatrix(Relems), dt) {} /** * Constructs a controller with the given coefficients and plant. @@ -85,7 +98,30 @@ class LinearQuadraticRegulator { const Matrixd& B, const Matrixd& Q, const Matrixd& R, - units::second_t dt); + units::second_t dt) { + Matrixd discA; + Matrixd discB; + DiscretizeAB(A, B, dt, &discA, &discB); + + if (!IsStabilizable(discA, discB)) { + std::string msg = fmt::format( + "The system passed to the LQR is unstabilizable!\n\nA =\n{}\nB " + "=\n{}\n", + discA, discB); + + wpi::math::MathSharedStore::ReportError(msg); + throw std::invalid_argument(msg); + } + + Matrixd S = DARE(discA, discB, Q, R); + + // K = (BᵀSB + R)⁻¹BᵀSA + m_K = (discB.transpose() * S * discB + R) + .llt() + .solve(discB.transpose() * S * discA); + + Reset(); + } /** * Constructs a controller with the given coefficients and plant. @@ -103,7 +139,20 @@ class LinearQuadraticRegulator { const Matrixd& Q, const Matrixd& R, const Matrixd& N, - units::second_t dt); + units::second_t dt) { + Matrixd discA; + Matrixd discB; + DiscretizeAB(A, B, dt, &discA, &discB); + + Matrixd S = DARE(discA, discB, Q, R, N); + + // K = (BᵀSB + R)⁻¹(BᵀSA + Nᵀ) + m_K = (discB.transpose() * S * discB + R) + .llt() + .solve(discB.transpose() * S * discA + N.transpose()); + + Reset(); + } LinearQuadraticRegulator(LinearQuadraticRegulator&&) = default; LinearQuadraticRegulator& operator=(LinearQuadraticRegulator&&) = default; @@ -166,7 +215,10 @@ class LinearQuadraticRegulator { * * @param x The current state x. */ - InputVector Calculate(const StateVector& x); + InputVector Calculate(const StateVector& x) { + m_u = m_K * (m_r - x); + return m_u; + } /** * Returns the next output of the controller. @@ -174,7 +226,10 @@ class LinearQuadraticRegulator { * @param x The current state x. * @param nextR The next reference vector r. */ - InputVector Calculate(const StateVector& x, const StateVector& nextR); + InputVector Calculate(const StateVector& x, const StateVector& nextR) { + m_r = nextR; + return Calculate(x); + } /** * Adjusts LQR controller gain to compensate for a pure time delay in the @@ -194,7 +249,13 @@ class LinearQuadraticRegulator { */ template void LatencyCompensate(const LinearSystem& plant, - units::second_t dt, units::second_t inputDelay); + units::second_t dt, units::second_t inputDelay) { + Matrixd discA; + Matrixd discB; + DiscretizeAB(plant.A(), plant.B(), dt, &discA, &discB); + + m_K = m_K * (discA - discB * m_K).pow(inputDelay / dt); + } private: // Current reference @@ -215,5 +276,3 @@ extern template class EXPORT_TEMPLATE_DECLARE(WPILIB_DLLEXPORT) LinearQuadraticRegulator<2, 2>; } // namespace frc - -#include "LinearQuadraticRegulator.inc" diff --git a/wpimath/src/main/native/include/frc/controller/LinearQuadraticRegulator.inc b/wpimath/src/main/native/include/frc/controller/LinearQuadraticRegulator.inc deleted file mode 100644 index 333181ce497..00000000000 --- a/wpimath/src/main/native/include/frc/controller/LinearQuadraticRegulator.inc +++ /dev/null @@ -1,110 +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 -#include - -#include -#include - -#include "frc/DARE.h" -#include "frc/StateSpaceUtil.h" -#include "frc/controller/LinearQuadraticRegulator.h" -#include "frc/fmt/Eigen.h" -#include "frc/system/Discretization.h" -#include "wpimath/MathShared.h" - -namespace frc { - -template -template -LinearQuadraticRegulator::LinearQuadraticRegulator( - const LinearSystem& plant, - const StateArray& Qelems, const InputArray& Relems, units::second_t dt) - : LinearQuadraticRegulator(plant.A(), plant.B(), Qelems, Relems, dt) {} - -template -LinearQuadraticRegulator::LinearQuadraticRegulator( - const Matrixd& A, const Matrixd& B, - const StateArray& Qelems, const InputArray& Relems, units::second_t dt) - : LinearQuadraticRegulator(A, B, MakeCostMatrix(Qelems), - MakeCostMatrix(Relems), dt) {} - -template -LinearQuadraticRegulator::LinearQuadraticRegulator( - const Matrixd& A, const Matrixd& B, - const Matrixd& Q, const Matrixd& R, - units::second_t dt) { - Matrixd discA; - Matrixd discB; - DiscretizeAB(A, B, dt, &discA, &discB); - - if (!IsStabilizable(discA, discB)) { - std::string msg = fmt::format( - "The system passed to the LQR is unstabilizable!\n\nA =\n{}\nB =\n{}\n", - discA, discB); - - wpi::math::MathSharedStore::ReportError(msg); - throw std::invalid_argument(msg); - } - - Matrixd S = DARE(discA, discB, Q, R); - - // K = (BᵀSB + R)⁻¹BᵀSA - m_K = (discB.transpose() * S * discB + R) - .llt() - .solve(discB.transpose() * S * discA); - - Reset(); -} - -template -LinearQuadraticRegulator::LinearQuadraticRegulator( - const Matrixd& A, const Matrixd& B, - const Matrixd& Q, const Matrixd& R, - const Matrixd& N, units::second_t dt) { - Matrixd discA; - Matrixd discB; - DiscretizeAB(A, B, dt, &discA, &discB); - - Matrixd S = DARE(discA, discB, Q, R, N); - - // K = (BᵀSB + R)⁻¹(BᵀSA + Nᵀ) - m_K = (discB.transpose() * S * discB + R) - .llt() - .solve(discB.transpose() * S * discA + N.transpose()); - - Reset(); -} - -template -typename LinearQuadraticRegulator::InputVector -LinearQuadraticRegulator::Calculate(const StateVector& x) { - m_u = m_K * (m_r - x); - return m_u; -} - -template -typename LinearQuadraticRegulator::InputVector -LinearQuadraticRegulator::Calculate(const StateVector& x, - const StateVector& nextR) { - m_r = nextR; - return Calculate(x); -} - -template -template -void LinearQuadraticRegulator::LatencyCompensate( - const LinearSystem& plant, units::second_t dt, - units::second_t inputDelay) { - Matrixd discA; - Matrixd discB; - DiscretizeAB(plant.A(), plant.B(), dt, &discA, &discB); - - m_K = m_K * (discA - discB * m_K).pow(inputDelay / dt); -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/controller/proto/SimpleMotorFeedforwardProto.h b/wpimath/src/main/native/include/frc/controller/proto/SimpleMotorFeedforwardProto.h index ad57d132d7b..4d763f0b195 100644 --- a/wpimath/src/main/native/include/frc/controller/proto/SimpleMotorFeedforwardProto.h +++ b/wpimath/src/main/native/include/frc/controller/proto/SimpleMotorFeedforwardProto.h @@ -4,8 +4,10 @@ #pragma once +#include #include +#include "controller.pb.h" #include "frc/controller/SimpleMotorFeedforward.h" #include "units/length.h" @@ -14,11 +16,35 @@ template struct wpi::Protobuf> { - static google::protobuf::Message* New(google::protobuf::Arena* arena); + static google::protobuf::Message* New(google::protobuf::Arena* arena) { + return wpi::CreateMessage( + arena); + } + static frc::SimpleMotorFeedforward Unpack( - const google::protobuf::Message& msg); + const google::protobuf::Message& msg) { + auto m = + static_cast(&msg); + return {units::volt_t{m->ks()}, + units::unit_t::kv_unit>{ + m->kv()}, + units::unit_t::ka_unit>{ + m->ka()}, + units::second_t{m->dt()}}; + } + static void Pack(google::protobuf::Message* msg, - const frc::SimpleMotorFeedforward& value); + const frc::SimpleMotorFeedforward& value) { + auto m = static_cast(msg); + m->set_ks(value.GetKs().value()); + m->set_kv( + units::unit_t::kv_unit>{ + value.GetKv()} + .value()); + m->set_ka( + units::unit_t::ka_unit>{ + value.GetKa()} + .value()); + m->set_dt(units::second_t{value.GetDt()}.value()); + } }; - -#include "frc/controller/proto/SimpleMotorFeedforwardProto.inc" diff --git a/wpimath/src/main/native/include/frc/controller/proto/SimpleMotorFeedforwardProto.inc b/wpimath/src/main/native/include/frc/controller/proto/SimpleMotorFeedforwardProto.inc deleted file mode 100644 index 8cda505a3db..00000000000 --- a/wpimath/src/main/native/include/frc/controller/proto/SimpleMotorFeedforwardProto.inc +++ /dev/null @@ -1,45 +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 - -#include "controller.pb.h" -#include "frc/controller/proto/SimpleMotorFeedforwardProto.h" - -template -google::protobuf::Message* -wpi::Protobuf>::New( - google::protobuf::Arena* arena) { - return wpi::CreateMessage(arena); -} - -template -frc::SimpleMotorFeedforward -wpi::Protobuf>::Unpack( - const google::protobuf::Message& msg) { - auto m = static_cast(&msg); - return {units::volt_t{m->ks()}, - units::unit_t::kv_unit>{ - m->kv()}, - units::unit_t::ka_unit>{ - m->ka()}, - units::second_t{m->dt()}}; -} - -template -void wpi::Protobuf>::Pack( - google::protobuf::Message* msg, - const frc::SimpleMotorFeedforward& value) { - auto m = static_cast(msg); - m->set_ks(value.GetKs().value()); - m->set_kv(units::unit_t::kv_unit>{ - value.GetKv()} - .value()); - m->set_ka(units::unit_t::ka_unit>{ - value.GetKa()} - .value()); - m->set_dt(units::second_t{value.GetDt()}.value()); -} diff --git a/wpimath/src/main/native/include/frc/controller/struct/SimpleMotorFeedforwardStruct.h b/wpimath/src/main/native/include/frc/controller/struct/SimpleMotorFeedforwardStruct.h index 1ebbefa3633..156eef5d4b3 100644 --- a/wpimath/src/main/native/include/frc/controller/struct/SimpleMotorFeedforwardStruct.h +++ b/wpimath/src/main/native/include/frc/controller/struct/SimpleMotorFeedforwardStruct.h @@ -24,14 +24,41 @@ struct wpi::Struct> { } static frc::SimpleMotorFeedforward Unpack( - std::span data); + std::span data) { + constexpr size_t kKsOff = 0; + constexpr size_t kKvOff = kKsOff + 8; + constexpr size_t kKaOff = kKvOff + 8; + constexpr size_t kDtOff = kKaOff + 8; + return {units::volt_t{wpi::UnpackStruct(data)}, + units::unit_t::kv_unit>{ + wpi::UnpackStruct(data)}, + units::unit_t::ka_unit>{ + wpi::UnpackStruct(data)}, + units::second_t{wpi::UnpackStruct(data)}}; + } + static void Pack(std::span data, - const frc::SimpleMotorFeedforward& value); + const frc::SimpleMotorFeedforward& value) { + constexpr size_t kKsOff = 0; + constexpr size_t kKvOff = kKsOff + 8; + constexpr size_t kKaOff = kKvOff + 8; + constexpr size_t kDtOff = kKaOff + 8; + wpi::PackStruct(data, value.GetKs().value()); + wpi::PackStruct( + data, + units::unit_t::kv_unit>{ + value.GetKv()} + .value()); + wpi::PackStruct( + data, + units::unit_t::ka_unit>{ + value.GetKa()} + .value()); + wpi::PackStruct(data, units::second_t{value.GetDt()}.value()); + } }; static_assert( wpi::StructSerializable>); static_assert( wpi::StructSerializable>); - -#include "frc/controller/struct/SimpleMotorFeedforwardStruct.inc" diff --git a/wpimath/src/main/native/include/frc/controller/struct/SimpleMotorFeedforwardStruct.inc b/wpimath/src/main/native/include/frc/controller/struct/SimpleMotorFeedforwardStruct.inc deleted file mode 100644 index 50c6760f958..00000000000 --- a/wpimath/src/main/native/include/frc/controller/struct/SimpleMotorFeedforwardStruct.inc +++ /dev/null @@ -1,45 +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 "frc/controller/struct/SimpleMotorFeedforwardStruct.h" - -template -frc::SimpleMotorFeedforward -wpi::Struct>::Unpack( - std::span data) { - constexpr size_t kKsOff = 0; - constexpr size_t kKvOff = kKsOff + 8; - constexpr size_t kKaOff = kKvOff + 8; - constexpr size_t kDtOff = kKaOff + 8; - return {units::volt_t{wpi::UnpackStruct(data)}, - units::unit_t::kv_unit>{ - wpi::UnpackStruct(data)}, - units::unit_t::ka_unit>{ - wpi::UnpackStruct(data)}, - units::second_t{wpi::UnpackStruct(data)}}; -} - -template -void wpi::Struct>::Pack( - std::span data, - const frc::SimpleMotorFeedforward& value) { - constexpr size_t kKsOff = 0; - constexpr size_t kKvOff = kKsOff + 8; - constexpr size_t kKaOff = kKvOff + 8; - constexpr size_t kDtOff = kKaOff + 8; - wpi::PackStruct(data, value.GetKs().value()); - wpi::PackStruct( - data, - units::unit_t::kv_unit>{ - value.GetKv()} - .value()); - wpi::PackStruct( - data, - units::unit_t::ka_unit>{ - value.GetKa()} - .value()); - wpi::PackStruct(data, units::second_t{value.GetDt()}.value()); -} diff --git a/wpimath/src/main/native/include/frc/estimator/ExtendedKalmanFilter.h b/wpimath/src/main/native/include/frc/estimator/ExtendedKalmanFilter.h index ec8a3ec7d65..89a28dc248f 100644 --- a/wpimath/src/main/native/include/frc/estimator/ExtendedKalmanFilter.h +++ b/wpimath/src/main/native/include/frc/estimator/ExtendedKalmanFilter.h @@ -5,10 +5,17 @@ #pragma once #include +#include +#include #include +#include "frc/DARE.h" #include "frc/EigenCore.h" +#include "frc/StateSpaceUtil.h" +#include "frc/system/Discretization.h" +#include "frc/system/NumericalIntegration.h" +#include "frc/system/NumericalJacobian.h" #include "units/time.h" namespace frc { @@ -68,7 +75,38 @@ class ExtendedKalmanFilter { std::function f, std::function h, const StateArray& stateStdDevs, const OutputArray& measurementStdDevs, - units::second_t dt); + units::second_t dt) + : m_f(std::move(f)), m_h(std::move(h)) { + m_contQ = MakeCovMatrix(stateStdDevs); + m_contR = MakeCovMatrix(measurementStdDevs); + m_residualFuncY = [](const OutputVector& a, + const OutputVector& b) -> OutputVector { + return a - b; + }; + m_addFuncX = [](const StateVector& a, const StateVector& b) -> StateVector { + return a + b; + }; + m_dt = dt; + + StateMatrix contA = NumericalJacobianX( + m_f, m_xHat, InputVector::Zero()); + Matrixd C = NumericalJacobianX( + m_h, m_xHat, InputVector::Zero()); + + StateMatrix discA; + StateMatrix discQ; + DiscretizeAQ(contA, m_contQ, dt, &discA, &discQ); + + Matrixd discR = DiscretizeR(m_contR, dt); + + if (IsDetectable(discA, C) && Outputs <= States) { + m_initP = + DARE(discA.transpose(), C.transpose(), discQ, discR); + } else { + m_initP = StateMatrix::Zero(); + } + m_P = m_initP; + } /** * Constructs an extended Kalman filter. @@ -96,7 +134,34 @@ class ExtendedKalmanFilter { residualFuncY, std::function addFuncX, - units::second_t dt); + units::second_t dt) + : m_f(std::move(f)), + m_h(std::move(h)), + m_residualFuncY(std::move(residualFuncY)), + m_addFuncX(std::move(addFuncX)) { + m_contQ = MakeCovMatrix(stateStdDevs); + m_contR = MakeCovMatrix(measurementStdDevs); + m_dt = dt; + + StateMatrix contA = NumericalJacobianX( + m_f, m_xHat, InputVector::Zero()); + Matrixd C = NumericalJacobianX( + m_h, m_xHat, InputVector::Zero()); + + StateMatrix discA; + StateMatrix discQ; + DiscretizeAQ(contA, m_contQ, dt, &discA, &discQ); + + Matrixd discR = DiscretizeR(m_contR, dt); + + if (IsDetectable(discA, C) && Outputs <= States) { + m_initP = + DARE(discA.transpose(), C.transpose(), discQ, discR); + } else { + m_initP = StateMatrix::Zero(); + } + m_P = m_initP; + } /** * Returns the error covariance matrix P. @@ -159,7 +224,23 @@ class ExtendedKalmanFilter { * @param u New control input from controller. * @param dt Timestep for prediction. */ - void Predict(const InputVector& u, units::second_t dt); + void Predict(const InputVector& u, units::second_t dt) { + // Find continuous A + StateMatrix contA = + NumericalJacobianX(m_f, m_xHat, u); + + // Find discrete A and Q + StateMatrix discA; + StateMatrix discQ; + DiscretizeAQ(contA, m_contQ, dt, &discA, &discQ); + + m_xHat = RK4(m_f, m_xHat, u, dt); + + // Pₖ₊₁⁻ = APₖ⁻Aᵀ + Q + m_P = discA * m_P * discA.transpose() + discQ; + + m_dt = dt; + } /** * Correct the state estimate x-hat using the measurements in y. @@ -202,7 +283,16 @@ class ExtendedKalmanFilter { void Correct( const InputVector& u, const Vectord& y, std::function(const StateVector&, const InputVector&)> h, - const Matrixd& R); + const Matrixd& R) { + auto residualFuncY = [](const Vectord& a, + const Vectord& b) -> Vectord { + return a - b; + }; + auto addFuncX = [](const StateVector& a, + const StateVector& b) -> StateVector { return a + b; }; + Correct(u, y, std::move(h), R, std::move(residualFuncY), + std::move(addFuncX)); + } /** * Correct the state estimate x-hat using the measurements in y. @@ -228,7 +318,37 @@ class ExtendedKalmanFilter { std::function(const Vectord&, const Vectord&)> residualFuncY, std::function - addFuncX); + addFuncX) { + const Matrixd C = + NumericalJacobianX(h, m_xHat, u); + const Matrixd discR = DiscretizeR(R, m_dt); + + Matrixd S = C * m_P * C.transpose() + discR; + + // We want to put K = PCᵀS⁻¹ into Ax = b form so we can solve it more + // efficiently. + // + // K = PCᵀS⁻¹ + // KS = PCᵀ + // (KS)ᵀ = (PCᵀ)ᵀ + // SᵀKᵀ = CPᵀ + // + // The solution of Ax = b can be found via x = A.solve(b). + // + // Kᵀ = Sᵀ.solve(CPᵀ) + // K = (Sᵀ.solve(CPᵀ))ᵀ + Matrixd K = + S.transpose().ldlt().solve(C * m_P.transpose()).transpose(); + + // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + Kₖ₊₁(y − h(x̂ₖ₊₁⁻, uₖ₊₁)) + m_xHat = addFuncX(m_xHat, K * residualFuncY(y, h(m_xHat, u))); + + // Pₖ₊₁⁺ = (I−Kₖ₊₁C)Pₖ₊₁⁻(I−Kₖ₊₁C)ᵀ + Kₖ₊₁RKₖ₊₁ᵀ + // Use Joseph form for numerical stability + m_P = (StateMatrix::Identity() - K * C) * m_P * + (StateMatrix::Identity() - K * C).transpose() + + K * discR * K.transpose(); + } private: std::function m_f; @@ -246,5 +366,3 @@ class ExtendedKalmanFilter { }; } // namespace frc - -#include "ExtendedKalmanFilter.inc" diff --git a/wpimath/src/main/native/include/frc/estimator/ExtendedKalmanFilter.inc b/wpimath/src/main/native/include/frc/estimator/ExtendedKalmanFilter.inc deleted file mode 100644 index b31d35b742f..00000000000 --- a/wpimath/src/main/native/include/frc/estimator/ExtendedKalmanFilter.inc +++ /dev/null @@ -1,171 +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 -#include - -#include - -#include "frc/DARE.h" -#include "frc/StateSpaceUtil.h" -#include "frc/estimator/ExtendedKalmanFilter.h" -#include "frc/system/Discretization.h" -#include "frc/system/NumericalIntegration.h" -#include "frc/system/NumericalJacobian.h" - -namespace frc { - -template -ExtendedKalmanFilter::ExtendedKalmanFilter( - std::function f, - std::function h, - const StateArray& stateStdDevs, const OutputArray& measurementStdDevs, - units::second_t dt) - : m_f(std::move(f)), m_h(std::move(h)) { - m_contQ = MakeCovMatrix(stateStdDevs); - m_contR = MakeCovMatrix(measurementStdDevs); - m_residualFuncY = [](const OutputVector& a, - const OutputVector& b) -> OutputVector { return a - b; }; - m_addFuncX = [](const StateVector& a, const StateVector& b) -> StateVector { - return a + b; - }; - m_dt = dt; - - StateMatrix contA = NumericalJacobianX( - m_f, m_xHat, InputVector::Zero()); - Matrixd C = NumericalJacobianX( - m_h, m_xHat, InputVector::Zero()); - - StateMatrix discA; - StateMatrix discQ; - DiscretizeAQ(contA, m_contQ, dt, &discA, &discQ); - - Matrixd discR = DiscretizeR(m_contR, dt); - - if (IsDetectable(discA, C) && Outputs <= States) { - m_initP = - DARE(discA.transpose(), C.transpose(), discQ, discR); - } else { - m_initP = StateMatrix::Zero(); - } - m_P = m_initP; -} - -template -ExtendedKalmanFilter::ExtendedKalmanFilter( - std::function f, - std::function h, - const StateArray& stateStdDevs, const OutputArray& measurementStdDevs, - std::function - residualFuncY, - std::function addFuncX, - units::second_t dt) - : m_f(std::move(f)), - m_h(std::move(h)), - m_residualFuncY(std::move(residualFuncY)), - m_addFuncX(std::move(addFuncX)) { - m_contQ = MakeCovMatrix(stateStdDevs); - m_contR = MakeCovMatrix(measurementStdDevs); - m_dt = dt; - - StateMatrix contA = NumericalJacobianX( - m_f, m_xHat, InputVector::Zero()); - Matrixd C = NumericalJacobianX( - m_h, m_xHat, InputVector::Zero()); - - StateMatrix discA; - StateMatrix discQ; - DiscretizeAQ(contA, m_contQ, dt, &discA, &discQ); - - Matrixd discR = DiscretizeR(m_contR, dt); - - if (IsDetectable(discA, C) && Outputs <= States) { - m_initP = - DARE(discA.transpose(), C.transpose(), discQ, discR); - } else { - m_initP = StateMatrix::Zero(); - } - m_P = m_initP; -} - -template -void ExtendedKalmanFilter::Predict( - const InputVector& u, units::second_t dt) { - // Find continuous A - StateMatrix contA = - NumericalJacobianX(m_f, m_xHat, u); - - // Find discrete A and Q - StateMatrix discA; - StateMatrix discQ; - DiscretizeAQ(contA, m_contQ, dt, &discA, &discQ); - - m_xHat = RK4(m_f, m_xHat, u, dt); - - // Pₖ₊₁⁻ = APₖ⁻Aᵀ + Q - m_P = discA * m_P * discA.transpose() + discQ; - - m_dt = dt; -} - -template -template -void ExtendedKalmanFilter::Correct( - const InputVector& u, const Vectord& y, - std::function(const StateVector&, const InputVector&)> h, - const Matrixd& R) { - auto residualFuncY = [](const Vectord& a, - const Vectord& b) -> Vectord { - return a - b; - }; - auto addFuncX = [](const StateVector& a, - const StateVector& b) -> StateVector { return a + b; }; - Correct(u, y, std::move(h), R, std::move(residualFuncY), - std::move(addFuncX)); -} - -template -template -void ExtendedKalmanFilter::Correct( - const InputVector& u, const Vectord& y, - std::function(const StateVector&, const InputVector&)> h, - const Matrixd& R, - std::function(const Vectord&, const Vectord&)> - residualFuncY, - std::function - addFuncX) { - const Matrixd C = - NumericalJacobianX(h, m_xHat, u); - const Matrixd discR = DiscretizeR(R, m_dt); - - Matrixd S = C * m_P * C.transpose() + discR; - - // We want to put K = PCᵀS⁻¹ into Ax = b form so we can solve it more - // efficiently. - // - // K = PCᵀS⁻¹ - // KS = PCᵀ - // (KS)ᵀ = (PCᵀ)ᵀ - // SᵀKᵀ = CPᵀ - // - // The solution of Ax = b can be found via x = A.solve(b). - // - // Kᵀ = Sᵀ.solve(CPᵀ) - // K = (Sᵀ.solve(CPᵀ))ᵀ - Matrixd K = - S.transpose().ldlt().solve(C * m_P.transpose()).transpose(); - - // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + Kₖ₊₁(y − h(x̂ₖ₊₁⁻, uₖ₊₁)) - m_xHat = addFuncX(m_xHat, K * residualFuncY(y, h(m_xHat, u))); - - // Pₖ₊₁⁺ = (I−Kₖ₊₁C)Pₖ₊₁⁻(I−Kₖ₊₁C)ᵀ + Kₖ₊₁RKₖ₊₁ᵀ - // Use Joseph form for numerical stability - m_P = (StateMatrix::Identity() - K * C) * m_P * - (StateMatrix::Identity() - K * C).transpose() + - K * discR * K.transpose(); -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/estimator/KalmanFilter.h b/wpimath/src/main/native/include/frc/estimator/KalmanFilter.h index 54ee51bafc9..c0220b436a5 100644 --- a/wpimath/src/main/native/include/frc/estimator/KalmanFilter.h +++ b/wpimath/src/main/native/include/frc/estimator/KalmanFilter.h @@ -4,11 +4,21 @@ #pragma once +#include +#include +#include + +#include #include +#include "frc/DARE.h" #include "frc/EigenCore.h" +#include "frc/StateSpaceUtil.h" +#include "frc/fmt/Eigen.h" +#include "frc/system/Discretization.h" #include "frc/system/LinearSystem.h" #include "units/time.h" +#include "wpimath/MathShared.h" namespace frc { @@ -59,7 +69,37 @@ class KalmanFilter { */ KalmanFilter(LinearSystem& plant, const StateArray& stateStdDevs, - const OutputArray& measurementStdDevs, units::second_t dt); + const OutputArray& measurementStdDevs, units::second_t dt) { + m_plant = &plant; + + m_contQ = MakeCovMatrix(stateStdDevs); + m_contR = MakeCovMatrix(measurementStdDevs); + m_dt = dt; + + // Find discrete A and Q + Matrixd discA; + Matrixd discQ; + DiscretizeAQ(plant.A(), m_contQ, dt, &discA, &discQ); + + Matrixd discR = DiscretizeR(m_contR, dt); + + const auto& C = plant.C(); + + if (!IsDetectable(discA, C)) { + std::string msg = fmt::format( + "The system passed to the Kalman filter is undetectable!\n\n" + "A =\n{}\nC =\n{}\n", + discA, C); + + wpi::math::MathSharedStore::ReportError(msg); + throw std::invalid_argument(msg); + } + + m_initP = + DARE(discA.transpose(), C.transpose(), discQ, discR); + + Reset(); + } /** * Returns the error covariance matrix P. @@ -122,7 +162,19 @@ class KalmanFilter { * @param u New control input from controller. * @param dt Timestep for prediction. */ - void Predict(const InputVector& u, units::second_t dt); + void Predict(const InputVector& u, units::second_t dt) { + // Find discrete A and Q + StateMatrix discA; + StateMatrix discQ; + DiscretizeAQ(m_plant->A(), m_contQ, dt, &discA, &discQ); + + m_xHat = m_plant->CalculateX(m_xHat, u, dt); + + // Pₖ₊₁⁻ = APₖ⁻Aᵀ + Q + m_P = discA * m_P * discA.transpose() + discQ; + + m_dt = dt; + } /** * Correct the state estimate x-hat using the measurements in y. @@ -144,7 +196,38 @@ class KalmanFilter { * @param R Continuous measurement noise covariance matrix. */ void Correct(const InputVector& u, const OutputVector& y, - const Matrixd& R); + const Matrixd& R) { + const auto& C = m_plant->C(); + const auto& D = m_plant->D(); + + const Matrixd discR = DiscretizeR(R, m_dt); + + Matrixd S = C * m_P * C.transpose() + discR; + + // We want to put K = PCᵀS⁻¹ into Ax = b form so we can solve it more + // efficiently. + // + // K = PCᵀS⁻¹ + // KS = PCᵀ + // (KS)ᵀ = (PCᵀ)ᵀ + // SᵀKᵀ = CPᵀ + // + // The solution of Ax = b can be found via x = A.solve(b). + // + // Kᵀ = Sᵀ.solve(CPᵀ) + // K = (Sᵀ.solve(CPᵀ))ᵀ + Matrixd K = + S.transpose().ldlt().solve(C * m_P.transpose()).transpose(); + + // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − (Cx̂ₖ₊₁⁻ + Duₖ₊₁)) + m_xHat += K * (y - (C * m_xHat + D * u)); + + // Pₖ₊₁⁺ = (I−Kₖ₊₁C)Pₖ₊₁⁻(I−Kₖ₊₁C)ᵀ + Kₖ₊₁RKₖ₊₁ᵀ + // Use Joseph form for numerical stability + m_P = (StateMatrix::Identity() - K * C) * m_P * + (StateMatrix::Identity() - K * C).transpose() + + K * discR * K.transpose(); + } private: LinearSystem* m_plant; @@ -163,5 +246,3 @@ extern template class EXPORT_TEMPLATE_DECLARE(WPILIB_DLLEXPORT) KalmanFilter<2, 1, 1>; } // namespace frc - -#include "KalmanFilter.inc" diff --git a/wpimath/src/main/native/include/frc/estimator/KalmanFilter.inc b/wpimath/src/main/native/include/frc/estimator/KalmanFilter.inc deleted file mode 100644 index a00b455b316..00000000000 --- a/wpimath/src/main/native/include/frc/estimator/KalmanFilter.inc +++ /dev/null @@ -1,110 +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 -#include -#include - -#include - -#include "frc/DARE.h" -#include "frc/StateSpaceUtil.h" -#include "frc/estimator/KalmanFilter.h" -#include "frc/fmt/Eigen.h" -#include "frc/system/Discretization.h" -#include "wpimath/MathShared.h" - -namespace frc { - -template -KalmanFilter::KalmanFilter( - LinearSystem& plant, - const StateArray& stateStdDevs, const OutputArray& measurementStdDevs, - units::second_t dt) { - m_plant = &plant; - - m_contQ = MakeCovMatrix(stateStdDevs); - m_contR = MakeCovMatrix(measurementStdDevs); - m_dt = dt; - - // Find discrete A and Q - Matrixd discA; - Matrixd discQ; - DiscretizeAQ(plant.A(), m_contQ, dt, &discA, &discQ); - - Matrixd discR = DiscretizeR(m_contR, dt); - - const auto& C = plant.C(); - - if (!IsDetectable(discA, C)) { - std::string msg = fmt::format( - "The system passed to the Kalman filter is undetectable!\n\n" - "A =\n{}\nC =\n{}\n", - discA, C); - - wpi::math::MathSharedStore::ReportError(msg); - throw std::invalid_argument(msg); - } - - m_initP = - DARE(discA.transpose(), C.transpose(), discQ, discR); - - Reset(); -} - -template -void KalmanFilter::Predict(const InputVector& u, - units::second_t dt) { - // Find discrete A and Q - StateMatrix discA; - StateMatrix discQ; - DiscretizeAQ(m_plant->A(), m_contQ, dt, &discA, &discQ); - - m_xHat = m_plant->CalculateX(m_xHat, u, dt); - - // Pₖ₊₁⁻ = APₖ⁻Aᵀ + Q - m_P = discA * m_P * discA.transpose() + discQ; - - m_dt = dt; -} - -template -void KalmanFilter::Correct( - const InputVector& u, const OutputVector& y, - const Matrixd& R) { - const auto& C = m_plant->C(); - const auto& D = m_plant->D(); - - const Matrixd discR = DiscretizeR(R, m_dt); - - Matrixd S = C * m_P * C.transpose() + discR; - - // We want to put K = PCᵀS⁻¹ into Ax = b form so we can solve it more - // efficiently. - // - // K = PCᵀS⁻¹ - // KS = PCᵀ - // (KS)ᵀ = (PCᵀ)ᵀ - // SᵀKᵀ = CPᵀ - // - // The solution of Ax = b can be found via x = A.solve(b). - // - // Kᵀ = Sᵀ.solve(CPᵀ) - // K = (Sᵀ.solve(CPᵀ))ᵀ - Matrixd K = - S.transpose().ldlt().solve(C * m_P.transpose()).transpose(); - - // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − (Cx̂ₖ₊₁⁻ + Duₖ₊₁)) - m_xHat += K * (y - (C * m_xHat + D * u)); - - // Pₖ₊₁⁺ = (I−Kₖ₊₁C)Pₖ₊₁⁻(I−Kₖ₊₁C)ᵀ + Kₖ₊₁RKₖ₊₁ᵀ - // Use Joseph form for numerical stability - m_P = (StateMatrix::Identity() - K * C) * m_P * - (StateMatrix::Identity() - K * C).transpose() + - K * discR * K.transpose(); -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/estimator/PoseEstimator.h b/wpimath/src/main/native/include/frc/estimator/PoseEstimator.h index f75a5afec73..1f4a88be2b8 100644 --- a/wpimath/src/main/native/include/frc/estimator/PoseEstimator.h +++ b/wpimath/src/main/native/include/frc/estimator/PoseEstimator.h @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -23,6 +22,7 @@ #include "wpimath/MathShared.h" namespace frc { + /** * This class wraps odometry to fuse latency-compensated * vision measurements with encoder measurements. Robot code should not use this @@ -59,7 +59,14 @@ class WPILIB_DLLEXPORT PoseEstimator { PoseEstimator(Kinematics& kinematics, Odometry& odometry, const wpi::array& stateStdDevs, - const wpi::array& visionMeasurementStdDevs); + const wpi::array& visionMeasurementStdDevs) + : m_odometry(odometry), m_poseEstimate(m_odometry.GetPose()) { + for (size_t i = 0; i < 3; ++i) { + m_q[i] = stateStdDevs[i] * stateStdDevs[i]; + } + + SetVisionMeasurementStdDevs(visionMeasurementStdDevs); + } /** * Sets the pose estimator's trust in vision measurements. This might be used @@ -72,7 +79,23 @@ class WPILIB_DLLEXPORT PoseEstimator { * less. */ void SetVisionMeasurementStdDevs( - const wpi::array& visionMeasurementStdDevs); + const wpi::array& visionMeasurementStdDevs) { + wpi::array r{wpi::empty_array}; + for (size_t i = 0; i < 3; ++i) { + r[i] = visionMeasurementStdDevs[i] * visionMeasurementStdDevs[i]; + } + + // Solve for closed form Kalman gain for continuous Kalman filter with A = 0 + // and C = I. See wpimath/algorithms.md. + for (size_t row = 0; row < 3; ++row) { + if (m_q[row] == 0.0) { + m_visionK(row, row) = 0.0; + } else { + m_visionK(row, row) = + m_q[row] / (m_q[row] + std::sqrt(m_q[row] * r[row])); + } + } + } /** * Resets the robot's position on the field. @@ -85,35 +108,50 @@ class WPILIB_DLLEXPORT PoseEstimator { * @param pose The estimated pose of the robot on the field. */ void ResetPosition(const Rotation2d& gyroAngle, - const WheelPositions& wheelPositions, const Pose2d& pose); + const WheelPositions& wheelPositions, const Pose2d& pose) { + // Reset state estimate and error covariance + m_odometry.ResetPosition(gyroAngle, wheelPositions, pose); + m_odometryPoseBuffer.Clear(); + m_visionUpdates.clear(); + m_poseEstimate = m_odometry.GetPose(); + } /** * Resets the robot's pose. * * @param pose The pose to reset to. */ - void ResetPose(const Pose2d& pose); + void ResetPose(const Pose2d& pose) { + m_odometry.ResetPose(pose); + m_odometryPoseBuffer.Clear(); + } /** * Resets the robot's translation. * * @param translation The pose to translation to. */ - void ResetTranslation(const Translation2d& translation); + void ResetTranslation(const Translation2d& translation) { + m_odometry.ResetTranslation(translation); + m_odometryPoseBuffer.Clear(); + } /** * Resets the robot's rotation. * * @param rotation The rotation to reset to. */ - void ResetRotation(const Rotation2d& rotation); + void ResetRotation(const Rotation2d& rotation) { + m_odometry.ResetRotation(rotation); + m_odometryPoseBuffer.Clear(); + } /** * Gets the estimated robot pose. * * @return The estimated robot pose in meters. */ - Pose2d GetEstimatedPosition() const; + Pose2d GetEstimatedPosition() const { return m_poseEstimate; } /** * Return the pose at a given timestamp, if the buffer is not empty. @@ -122,7 +160,47 @@ class WPILIB_DLLEXPORT PoseEstimator { * @return The pose at the given timestamp (or std::nullopt if the buffer is * empty). */ - std::optional SampleAt(units::second_t timestamp) const; + std::optional SampleAt(units::second_t timestamp) const { + // Step 0: If there are no odometry updates to sample, skip. + if (m_odometryPoseBuffer.GetInternalBuffer().empty()) { + return std::nullopt; + } + + // Step 1: Make sure timestamp matches the sample from the odometry pose + // buffer. (When sampling, the buffer will always use a timestamp + // between the first and last timestamps) + units::second_t oldestOdometryTimestamp = + m_odometryPoseBuffer.GetInternalBuffer().front().first; + units::second_t newestOdometryTimestamp = + m_odometryPoseBuffer.GetInternalBuffer().back().first; + timestamp = + std::clamp(timestamp, oldestOdometryTimestamp, newestOdometryTimestamp); + + // Step 2: If there are no applicable vision updates, use the odometry-only + // information. + if (m_visionUpdates.empty() || timestamp < m_visionUpdates.begin()->first) { + return m_odometryPoseBuffer.Sample(timestamp); + } + + // Step 3: Get the latest vision update from before or at the timestamp to + // sample at. + // First, find the iterator past the sample timestamp, then go back one. + // Note that upper_bound() won't return begin() because we check begin() + // earlier. + auto floorIter = m_visionUpdates.upper_bound(timestamp); + --floorIter; + auto visionUpdate = floorIter->second; + + // Step 4: Get the pose measured by odometry at the time of the sample. + auto odometryEstimate = m_odometryPoseBuffer.Sample(timestamp); + + // Step 5: Apply the vision compensation to the odometry pose. + // TODO Replace with std::optional::transform() in C++23 + if (odometryEstimate) { + return visionUpdate.Compensate(*odometryEstimate); + } + return std::nullopt; + } /** * Adds a vision measurement to the Kalman Filter. This will correct @@ -145,7 +223,63 @@ class WPILIB_DLLEXPORT PoseEstimator { * frc::Timer::GetFPGATimestamp() as your time source in this case. */ void AddVisionMeasurement(const Pose2d& visionRobotPose, - units::second_t timestamp); + units::second_t timestamp) { + // Step 0: If this measurement is old enough to be outside the pose buffer's + // timespan, skip. + if (m_odometryPoseBuffer.GetInternalBuffer().empty() || + m_odometryPoseBuffer.GetInternalBuffer().front().first - + kBufferDuration > + timestamp) { + return; + } + + // Step 1: Clean up any old entries + CleanUpVisionUpdates(); + + // Step 2: Get the pose measured by odometry at the moment the vision + // measurement was made. + auto odometrySample = m_odometryPoseBuffer.Sample(timestamp); + + if (!odometrySample) { + return; + } + + // Step 3: Get the vision-compensated pose estimate at the moment the vision + // measurement was made. + auto visionSample = SampleAt(timestamp); + + if (!visionSample) { + return; + } + + // Step 4: Measure the twist between the old pose estimate and the vision + // pose. + auto twist = visionSample.value().Log(visionRobotPose); + + // Step 5: We should not trust the twist entirely, so instead we scale this + // twist by a Kalman gain matrix representing how much we trust vision + // measurements compared to our current pose. + Eigen::Vector3d k_times_twist = + m_visionK * Eigen::Vector3d{twist.dx.value(), twist.dy.value(), + twist.dtheta.value()}; + + // Step 6: Convert back to Twist2d. + Twist2d scaledTwist{units::meter_t{k_times_twist(0)}, + units::meter_t{k_times_twist(1)}, + units::radian_t{k_times_twist(2)}}; + + // Step 7: Calculate and record the vision update. + VisionUpdate visionUpdate{visionSample->Exp(scaledTwist), *odometrySample}; + m_visionUpdates[timestamp] = visionUpdate; + + // Step 8: Remove later vision measurements. (Matches previous behavior) + auto firstAfter = m_visionUpdates.upper_bound(timestamp); + m_visionUpdates.erase(firstAfter, m_visionUpdates.end()); + + // Step 9: Update latest pose estimate. Since we cleared all updates after + // this vision update, it's guaranteed to be the latest vision update. + m_poseEstimate = visionUpdate.Compensate(m_odometry.GetPose()); + } /** * Adds a vision measurement to the Kalman Filter. This will correct @@ -192,7 +326,10 @@ class WPILIB_DLLEXPORT PoseEstimator { * @return The estimated pose of the robot in meters. */ Pose2d Update(const Rotation2d& gyroAngle, - const WheelPositions& wheelPositions); + const WheelPositions& wheelPositions) { + return UpdateWithTime(wpi::math::MathSharedStore::GetTimestamp(), gyroAngle, + wheelPositions); + } /** * Updates the pose estimator with wheel encoder and gyro information. This @@ -206,13 +343,53 @@ class WPILIB_DLLEXPORT PoseEstimator { */ Pose2d UpdateWithTime(units::second_t currentTime, const Rotation2d& gyroAngle, - const WheelPositions& wheelPositions); + const WheelPositions& wheelPositions) { + auto odometryEstimate = m_odometry.Update(gyroAngle, wheelPositions); + + m_odometryPoseBuffer.AddSample(currentTime, odometryEstimate); + + if (m_visionUpdates.empty()) { + m_poseEstimate = odometryEstimate; + } else { + auto visionUpdate = m_visionUpdates.rbegin()->second; + m_poseEstimate = visionUpdate.Compensate(odometryEstimate); + } + + return GetEstimatedPosition(); + } private: /** * Removes stale vision updates that won't affect sampling. */ - void CleanUpVisionUpdates(); + void CleanUpVisionUpdates() { + // Step 0: If there are no odometry samples, skip. + if (m_odometryPoseBuffer.GetInternalBuffer().empty()) { + return; + } + + // Step 1: Find the oldest timestamp that needs a vision update. + units::second_t oldestOdometryTimestamp = + m_odometryPoseBuffer.GetInternalBuffer().front().first; + + // Step 2: If there are no vision updates before that timestamp, skip. + if (m_visionUpdates.empty() || + oldestOdometryTimestamp < m_visionUpdates.begin()->first) { + return; + } + + // Step 3: Find the newest vision update timestamp before or at the oldest + // timestamp. + // First, find the iterator past the oldest odometry timestamp, then go + // back one. Note that upper_bound() won't return begin() because we check + // begin() earlier. + auto newestNeededVisionUpdate = + m_visionUpdates.upper_bound(oldestOdometryTimestamp); + --newestNeededVisionUpdate; + + // Step 4: Remove all entries strictly before the newest timestamp we need. + m_visionUpdates.erase(m_visionUpdates.begin(), newestNeededVisionUpdate); + } struct VisionUpdate { // The vision-compensated pose estimate @@ -250,6 +427,5 @@ class WPILIB_DLLEXPORT PoseEstimator { Pose2d m_poseEstimate; }; -} // namespace frc -#include "frc/estimator/PoseEstimator.inc" +} // namespace frc diff --git a/wpimath/src/main/native/include/frc/estimator/PoseEstimator.inc b/wpimath/src/main/native/include/frc/estimator/PoseEstimator.inc deleted file mode 100644 index 51bb8343062..00000000000 --- a/wpimath/src/main/native/include/frc/estimator/PoseEstimator.inc +++ /dev/null @@ -1,246 +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 "frc/estimator/PoseEstimator.h" -#include "frc/geometry/Pose2d.h" -#include "frc/geometry/Translation2d.h" - -namespace frc { - -template -PoseEstimator::PoseEstimator( - Kinematics& kinematics, - Odometry& odometry, - const wpi::array& stateStdDevs, - const wpi::array& visionMeasurementStdDevs) - : m_odometry(odometry), m_poseEstimate(m_odometry.GetPose()) { - for (size_t i = 0; i < 3; ++i) { - m_q[i] = stateStdDevs[i] * stateStdDevs[i]; - } - - SetVisionMeasurementStdDevs(visionMeasurementStdDevs); -} - -template -void PoseEstimator::SetVisionMeasurementStdDevs( - const wpi::array& visionMeasurementStdDevs) { - wpi::array r{wpi::empty_array}; - for (size_t i = 0; i < 3; ++i) { - r[i] = visionMeasurementStdDevs[i] * visionMeasurementStdDevs[i]; - } - - // Solve for closed form Kalman gain for continuous Kalman filter with A = 0 - // and C = I. See wpimath/algorithms.md. - for (size_t row = 0; row < 3; ++row) { - if (m_q[row] == 0.0) { - m_visionK(row, row) = 0.0; - } else { - m_visionK(row, row) = - m_q[row] / (m_q[row] + std::sqrt(m_q[row] * r[row])); - } - } -} - -template -void PoseEstimator::ResetPosition( - const Rotation2d& gyroAngle, const WheelPositions& wheelPositions, - const Pose2d& pose) { - // Reset state estimate and error covariance - m_odometry.ResetPosition(gyroAngle, wheelPositions, pose); - m_odometryPoseBuffer.Clear(); - m_visionUpdates.clear(); - m_poseEstimate = m_odometry.GetPose(); -} - -template -void PoseEstimator::ResetPose(const Pose2d& pose) { - m_odometry.ResetPose(pose); - m_odometryPoseBuffer.Clear(); -} - -template -void PoseEstimator::ResetTranslation( - const Translation2d& translation) { - m_odometry.ResetTranslation(translation); - m_odometryPoseBuffer.Clear(); -} - -template -void PoseEstimator::ResetRotation( - const Rotation2d& rotation) { - m_odometry.ResetRotation(rotation); - m_odometryPoseBuffer.Clear(); -} - -template -Pose2d PoseEstimator::GetEstimatedPosition() - const { - return m_poseEstimate; - if (m_visionUpdates.empty()) { - return m_odometry.GetPose(); - } - auto visionUpdate = m_visionUpdates.rbegin()->second; - return visionUpdate.Compensate(m_odometry.GetPose()); -} - -template -std::optional PoseEstimator::SampleAt( - units::second_t timestamp) const { - // Step 0: If there are no odometry updates to sample, skip. - if (m_odometryPoseBuffer.GetInternalBuffer().empty()) { - return std::nullopt; - } - - // Step 1: Make sure timestamp matches the sample from the odometry pose - // buffer. (When sampling, the buffer will always use a timestamp - // between the first and last timestamps) - units::second_t oldestOdometryTimestamp = - m_odometryPoseBuffer.GetInternalBuffer().front().first; - units::second_t newestOdometryTimestamp = - m_odometryPoseBuffer.GetInternalBuffer().back().first; - timestamp = - std::clamp(timestamp, oldestOdometryTimestamp, newestOdometryTimestamp); - - // Step 2: If there are no applicable vision updates, use the odometry-only - // information. - if (m_visionUpdates.empty() || timestamp < m_visionUpdates.begin()->first) { - return m_odometryPoseBuffer.Sample(timestamp); - } - - // Step 3: Get the latest vision update from before or at the timestamp to - // sample at. - // First, find the iterator past the sample timestamp, then go back one. Note - // that upper_bound() won't return begin() because we check begin() earlier. - auto floorIter = m_visionUpdates.upper_bound(timestamp); - --floorIter; - auto visionUpdate = floorIter->second; - - // Step 4: Get the pose measured by odometry at the time of the sample. - auto odometryEstimate = m_odometryPoseBuffer.Sample(timestamp); - - // Step 5: Apply the vision compensation to the odometry pose. - // TODO Replace with std::optional::transform() in C++23 - if (odometryEstimate) { - return visionUpdate.Compensate(*odometryEstimate); - } - return std::nullopt; -} - -template -void PoseEstimator::CleanUpVisionUpdates() { - // Step 0: If there are no odometry samples, skip. - if (m_odometryPoseBuffer.GetInternalBuffer().empty()) { - return; - } - - // Step 1: Find the oldest timestamp that needs a vision update. - units::second_t oldestOdometryTimestamp = - m_odometryPoseBuffer.GetInternalBuffer().front().first; - - // Step 2: If there are no vision updates before that timestamp, skip. - if (m_visionUpdates.empty() || - oldestOdometryTimestamp < m_visionUpdates.begin()->first) { - return; - } - - // Step 3: Find the newest vision update timestamp before or at the oldest - // timestamp. - // First, find the iterator past the oldest odometry timestamp, then go - // back one. Note that upper_bound() won't return begin() because we check - // begin() earlier. - auto newestNeededVisionUpdate = - m_visionUpdates.upper_bound(oldestOdometryTimestamp); - --newestNeededVisionUpdate; - - // Step 4: Remove all entries strictly before the newest timestamp we need. - m_visionUpdates.erase(m_visionUpdates.begin(), newestNeededVisionUpdate); -} - -template -void PoseEstimator::AddVisionMeasurement( - const Pose2d& visionRobotPose, units::second_t timestamp) { - // Step 0: If this measurement is old enough to be outside the pose buffer's - // timespan, skip. - if (m_odometryPoseBuffer.GetInternalBuffer().empty() || - m_odometryPoseBuffer.GetInternalBuffer().front().first - kBufferDuration > - timestamp) { - return; - } - - // Step 1: Clean up any old entries - CleanUpVisionUpdates(); - - // Step 2: Get the pose measured by odometry at the moment the vision - // measurement was made. - auto odometrySample = m_odometryPoseBuffer.Sample(timestamp); - - if (!odometrySample) { - return; - } - - // Step 3: Get the vision-compensated pose estimate at the moment the vision - // measurement was made. - auto visionSample = SampleAt(timestamp); - - if (!visionSample) { - return; - } - - // Step 4: Measure the twist between the old pose estimate and the vision - // pose. - auto twist = visionSample.value().Log(visionRobotPose); - - // Step 5: We should not trust the twist entirely, so instead we scale this - // twist by a Kalman gain matrix representing how much we trust vision - // measurements compared to our current pose. - Eigen::Vector3d k_times_twist = - m_visionK * - Eigen::Vector3d{twist.dx.value(), twist.dy.value(), twist.dtheta.value()}; - - // Step 6: Convert back to Twist2d. - Twist2d scaledTwist{units::meter_t{k_times_twist(0)}, - units::meter_t{k_times_twist(1)}, - units::radian_t{k_times_twist(2)}}; - - // Step 7: Calculate and record the vision update. - VisionUpdate visionUpdate{visionSample->Exp(scaledTwist), *odometrySample}; - m_visionUpdates[timestamp] = visionUpdate; - - // Step 8: Remove later vision measurements. (Matches previous behavior) - auto firstAfter = m_visionUpdates.upper_bound(timestamp); - m_visionUpdates.erase(firstAfter, m_visionUpdates.end()); - - // Step 9: Update latest pose estimate. Since we cleared all updates after - // this vision update, it's guaranteed to be the latest vision update. - m_poseEstimate = visionUpdate.Compensate(m_odometry.GetPose()); -} - -template -Pose2d PoseEstimator::Update( - const Rotation2d& gyroAngle, const WheelPositions& wheelPositions) { - return UpdateWithTime(wpi::math::MathSharedStore::GetTimestamp(), gyroAngle, - wheelPositions); -} - -template -Pose2d PoseEstimator::UpdateWithTime( - units::second_t currentTime, const Rotation2d& gyroAngle, - const WheelPositions& wheelPositions) { - auto odometryEstimate = m_odometry.Update(gyroAngle, wheelPositions); - - m_odometryPoseBuffer.AddSample(currentTime, odometryEstimate); - - if (m_visionUpdates.empty()) { - m_poseEstimate = odometryEstimate; - } else { - auto visionUpdate = m_visionUpdates.rbegin()->second; - m_poseEstimate = visionUpdate.Compensate(odometryEstimate); - } - - return GetEstimatedPosition(); -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/estimator/SteadyStateKalmanFilter.h b/wpimath/src/main/native/include/frc/estimator/SteadyStateKalmanFilter.h index c63e5802c60..31088e93cef 100644 --- a/wpimath/src/main/native/include/frc/estimator/SteadyStateKalmanFilter.h +++ b/wpimath/src/main/native/include/frc/estimator/SteadyStateKalmanFilter.h @@ -4,12 +4,22 @@ #pragma once +#include +#include +#include + +#include #include #include +#include "frc/DARE.h" #include "frc/EigenCore.h" +#include "frc/StateSpaceUtil.h" +#include "frc/fmt/Eigen.h" +#include "frc/system/Discretization.h" #include "frc/system/LinearSystem.h" #include "units/time.h" +#include "wpimath/MathShared.h" namespace frc { @@ -63,7 +73,52 @@ class SteadyStateKalmanFilter { SteadyStateKalmanFilter(LinearSystem& plant, const StateArray& stateStdDevs, const OutputArray& measurementStdDevs, - units::second_t dt); + units::second_t dt) { + m_plant = &plant; + + auto contQ = MakeCovMatrix(stateStdDevs); + auto contR = MakeCovMatrix(measurementStdDevs); + + Matrixd discA; + Matrixd discQ; + DiscretizeAQ(plant.A(), contQ, dt, &discA, &discQ); + + auto discR = DiscretizeR(contR, dt); + + const auto& C = plant.C(); + + if (!IsDetectable(discA, C)) { + std::string msg = fmt::format( + "The system passed to the Kalman filter is undetectable!\n\n" + "A =\n{}\nC =\n{}\n", + discA, C); + + wpi::math::MathSharedStore::ReportError(msg); + throw std::invalid_argument(msg); + } + + Matrixd P = + DARE(discA.transpose(), C.transpose(), discQ, discR); + + // S = CPCᵀ + R + Matrixd S = C * P * C.transpose() + discR; + + // We want to put K = PCᵀS⁻¹ into Ax = b form so we can solve it more + // efficiently. + // + // K = PCᵀS⁻¹ + // KS = PCᵀ + // (KS)ᵀ = (PCᵀ)ᵀ + // SᵀKᵀ = CPᵀ + // + // The solution of Ax = b can be found via x = A.solve(b). + // + // Kᵀ = Sᵀ.solve(CPᵀ) + // K = (Sᵀ.solve(CPᵀ))ᵀ + m_K = S.transpose().ldlt().solve(C * P.transpose()).transpose(); + + Reset(); + } SteadyStateKalmanFilter(SteadyStateKalmanFilter&&) = default; SteadyStateKalmanFilter& operator=(SteadyStateKalmanFilter&&) = default; @@ -119,7 +174,9 @@ class SteadyStateKalmanFilter { * @param u New control input from controller. * @param dt Timestep for prediction. */ - void Predict(const InputVector& u, units::second_t dt); + void Predict(const InputVector& u, units::second_t dt) { + m_xHat = m_plant->CalculateX(m_xHat, u, dt); + } /** * Correct the state estimate x-hat using the measurements in y. @@ -127,7 +184,13 @@ class SteadyStateKalmanFilter { * @param u Same control input used in the last predict step. * @param y Measurement vector. */ - void Correct(const InputVector& u, const OutputVector& y); + void Correct(const InputVector& u, const OutputVector& y) { + const auto& C = m_plant->C(); + const auto& D = m_plant->D(); + + // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − (Cx̂ₖ₊₁⁻ + Duₖ₊₁)) + m_xHat += m_K * (y - (C * m_xHat + D * u)); + } private: LinearSystem* m_plant; @@ -149,5 +212,3 @@ extern template class EXPORT_TEMPLATE_DECLARE(WPILIB_DLLEXPORT) SteadyStateKalmanFilter<2, 1, 1>; } // namespace frc - -#include "SteadyStateKalmanFilter.inc" diff --git a/wpimath/src/main/native/include/frc/estimator/SteadyStateKalmanFilter.inc b/wpimath/src/main/native/include/frc/estimator/SteadyStateKalmanFilter.inc deleted file mode 100644 index 2f75b241cca..00000000000 --- a/wpimath/src/main/native/include/frc/estimator/SteadyStateKalmanFilter.inc +++ /dev/null @@ -1,89 +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 -#include -#include - -#include - -#include "frc/DARE.h" -#include "frc/StateSpaceUtil.h" -#include "frc/estimator/SteadyStateKalmanFilter.h" -#include "frc/fmt/Eigen.h" -#include "frc/system/Discretization.h" -#include "wpimath/MathShared.h" - -namespace frc { - -template -SteadyStateKalmanFilter::SteadyStateKalmanFilter( - LinearSystem& plant, - const StateArray& stateStdDevs, const OutputArray& measurementStdDevs, - units::second_t dt) { - m_plant = &plant; - - auto contQ = MakeCovMatrix(stateStdDevs); - auto contR = MakeCovMatrix(measurementStdDevs); - - Matrixd discA; - Matrixd discQ; - DiscretizeAQ(plant.A(), contQ, dt, &discA, &discQ); - - auto discR = DiscretizeR(contR, dt); - - const auto& C = plant.C(); - - if (!IsDetectable(discA, C)) { - std::string msg = fmt::format( - "The system passed to the Kalman filter is undetectable!\n\n" - "A =\n{}\nC =\n{}\n", - discA, C); - - wpi::math::MathSharedStore::ReportError(msg); - throw std::invalid_argument(msg); - } - - Matrixd P = - DARE(discA.transpose(), C.transpose(), discQ, discR); - - // S = CPCᵀ + R - Matrixd S = C * P * C.transpose() + discR; - - // We want to put K = PCᵀS⁻¹ into Ax = b form so we can solve it more - // efficiently. - // - // K = PCᵀS⁻¹ - // KS = PCᵀ - // (KS)ᵀ = (PCᵀ)ᵀ - // SᵀKᵀ = CPᵀ - // - // The solution of Ax = b can be found via x = A.solve(b). - // - // Kᵀ = Sᵀ.solve(CPᵀ) - // K = (Sᵀ.solve(CPᵀ))ᵀ - m_K = S.transpose().ldlt().solve(C * P.transpose()).transpose(); - - Reset(); -} - -template -void SteadyStateKalmanFilter::Predict( - const InputVector& u, units::second_t dt) { - m_xHat = m_plant->CalculateX(m_xHat, u, dt); -} - -template -void SteadyStateKalmanFilter::Correct( - const InputVector& u, const OutputVector& y) { - const auto& C = m_plant->C(); - const auto& D = m_plant->D(); - - // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − (Cx̂ₖ₊₁⁻ + Duₖ₊₁)) - m_xHat += m_K * (y - (C * m_xHat + D * u)); -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/estimator/UnscentedKalmanFilter.h b/wpimath/src/main/native/include/frc/estimator/UnscentedKalmanFilter.h index df68e151606..87ee5ffd29b 100644 --- a/wpimath/src/main/native/include/frc/estimator/UnscentedKalmanFilter.h +++ b/wpimath/src/main/native/include/frc/estimator/UnscentedKalmanFilter.h @@ -5,12 +5,19 @@ #pragma once #include +#include +#include #include #include #include "frc/EigenCore.h" +#include "frc/StateSpaceUtil.h" #include "frc/estimator/MerweScaledSigmaPoints.h" +#include "frc/estimator/UnscentedTransform.h" +#include "frc/system/Discretization.h" +#include "frc/system/NumericalIntegration.h" +#include "frc/system/NumericalJacobian.h" #include "units/time.h" namespace frc { @@ -74,7 +81,31 @@ class UnscentedKalmanFilter { std::function f, std::function h, const StateArray& stateStdDevs, const OutputArray& measurementStdDevs, - units::second_t dt); + units::second_t dt) + : m_f(std::move(f)), m_h(std::move(h)) { + m_contQ = MakeCovMatrix(stateStdDevs); + m_contR = MakeCovMatrix(measurementStdDevs); + m_meanFuncX = [](const Matrixd& sigmas, + const Vectord<2 * States + 1>& Wm) -> StateVector { + return sigmas * Wm; + }; + m_meanFuncY = [](const Matrixd& sigmas, + const Vectord<2 * States + 1>& Wc) -> OutputVector { + return sigmas * Wc; + }; + m_residualFuncX = [](const StateVector& a, + const StateVector& b) -> StateVector { return a - b; }; + m_residualFuncY = [](const OutputVector& a, + const OutputVector& b) -> OutputVector { + return a - b; + }; + m_addFuncX = [](const StateVector& a, const StateVector& b) -> StateVector { + return a + b; + }; + m_dt = dt; + + Reset(); + } /** * Constructs an unscented Kalman filter with custom mean, residual, and @@ -120,7 +151,20 @@ class UnscentedKalmanFilter { residualFuncY, std::function addFuncX, - units::second_t dt); + units::second_t dt) + : m_f(std::move(f)), + m_h(std::move(h)), + m_meanFuncX(std::move(meanFuncX)), + m_meanFuncY(std::move(meanFuncY)), + m_residualFuncX(std::move(residualFuncX)), + m_residualFuncY(std::move(residualFuncY)), + m_addFuncX(std::move(addFuncX)) { + m_contQ = MakeCovMatrix(stateStdDevs); + m_contR = MakeCovMatrix(measurementStdDevs); + m_dt = dt; + + Reset(); + } /** * Returns the square-root error covariance matrix S. @@ -197,7 +241,31 @@ class UnscentedKalmanFilter { * @param u New control input from controller. * @param dt Timestep for prediction. */ - void Predict(const InputVector& u, units::second_t dt); + void Predict(const InputVector& u, units::second_t dt) { + m_dt = dt; + + // Discretize Q before projecting mean and covariance forward + StateMatrix contA = + NumericalJacobianX(m_f, m_xHat, u); + StateMatrix discA; + StateMatrix discQ; + DiscretizeAQ(contA, m_contQ, m_dt, &discA, &discQ); + Eigen::internal::llt_inplace::blocked(discQ); + + Matrixd sigmas = + m_pts.SquareRootSigmaPoints(m_xHat, m_S); + + for (int i = 0; i < m_pts.NumSigmas(); ++i) { + StateVector x = sigmas.template block(0, i); + m_sigmasF.template block(0, i) = RK4(m_f, x, u, dt); + } + + auto [xHat, S] = SquareRootUnscentedTransform( + m_sigmasF, m_pts.Wm(), m_pts.Wc(), m_meanFuncX, m_residualFuncX, + discQ.template triangularView()); + m_xHat = xHat; + m_S = S; + } /** * Correct the state estimate x-hat using the measurements in y. @@ -242,7 +310,25 @@ class UnscentedKalmanFilter { void Correct( const InputVector& u, const Vectord& y, std::function(const StateVector&, const InputVector&)> h, - const Matrixd& R); + const Matrixd& R) { + auto meanFuncY = [](const Matrixd& sigmas, + const Vectord<2 * States + 1>& Wc) -> Vectord { + return sigmas * Wc; + }; + auto residualFuncX = [](const StateVector& a, + const StateVector& b) -> StateVector { + return a - b; + }; + auto residualFuncY = [](const Vectord& a, + const Vectord& b) -> Vectord { + return a - b; + }; + auto addFuncX = [](const StateVector& a, + const StateVector& b) -> StateVector { return a + b; }; + Correct(u, y, std::move(h), R, std::move(meanFuncY), + std::move(residualFuncY), std::move(residualFuncX), + std::move(addFuncX)); + } /** * Correct the state estimate x-hat using the measurements in y. @@ -277,7 +363,54 @@ class UnscentedKalmanFilter { std::function residualFuncX, std::function - addFuncX); + addFuncX) { + Matrixd discR = DiscretizeR(R, m_dt); + Eigen::internal::llt_inplace::blocked(discR); + + // Transform sigma points into measurement space + Matrixd sigmasH; + Matrixd sigmas = + m_pts.SquareRootSigmaPoints(m_xHat, m_S); + for (int i = 0; i < m_pts.NumSigmas(); ++i) { + sigmasH.template block(0, i) = + h(sigmas.template block(0, i), u); + } + + // Mean and covariance of prediction passed through UT + auto [yHat, Sy] = SquareRootUnscentedTransform( + sigmasH, m_pts.Wm(), m_pts.Wc(), meanFuncY, residualFuncY, + discR.template triangularView()); + + // Compute cross covariance of the state and the measurements + Matrixd Pxy; + Pxy.setZero(); + for (int i = 0; i < m_pts.NumSigmas(); ++i) { + // Pxy += (sigmas_f[:, i] - x̂)(sigmas_h[:, i] - ŷ)ᵀ W_c[i] + Pxy += + m_pts.Wc(i) * + (residualFuncX(m_sigmasF.template block(0, i), m_xHat)) * + (residualFuncY(sigmasH.template block(0, i), yHat)) + .transpose(); + } + + // K = (P_{xy} / S_yᵀ) / S_y + // K = (S_y \ P_{xy}ᵀ)ᵀ / S_y + // K = (S_yᵀ \ (S_y \ P_{xy}ᵀ))ᵀ + Matrixd K = + Sy.transpose() + .fullPivHouseholderQr() + .solve(Sy.fullPivHouseholderQr().solve(Pxy.transpose())) + .transpose(); + + // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − ŷ) + m_xHat = addFuncX(m_xHat, K * residualFuncY(y, yHat)); + + Matrixd U = K * Sy; + for (int i = 0; i < Rows; i++) { + Eigen::internal::llt_inplace::rankUpdate( + m_S, U.template block(0, i), -1); + } + } private: std::function m_f; @@ -309,5 +442,3 @@ extern template class EXPORT_TEMPLATE_DECLARE(WPILIB_DLLEXPORT) UnscentedKalmanFilter<5, 3, 3>; } // namespace frc - -#include "UnscentedKalmanFilter.inc" diff --git a/wpimath/src/main/native/include/frc/estimator/UnscentedKalmanFilter.inc b/wpimath/src/main/native/include/frc/estimator/UnscentedKalmanFilter.inc deleted file mode 100644 index 03cfd192b4c..00000000000 --- a/wpimath/src/main/native/include/frc/estimator/UnscentedKalmanFilter.inc +++ /dev/null @@ -1,196 +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 -#include - -#include - -#include "frc/StateSpaceUtil.h" -#include "frc/estimator/UnscentedKalmanFilter.h" -#include "frc/estimator/UnscentedTransform.h" -#include "frc/system/Discretization.h" -#include "frc/system/NumericalIntegration.h" -#include "frc/system/NumericalJacobian.h" - -namespace frc { - -template -UnscentedKalmanFilter::UnscentedKalmanFilter( - std::function f, - std::function h, - const StateArray& stateStdDevs, const OutputArray& measurementStdDevs, - units::second_t dt) - : m_f(std::move(f)), m_h(std::move(h)) { - m_contQ = MakeCovMatrix(stateStdDevs); - m_contR = MakeCovMatrix(measurementStdDevs); - m_meanFuncX = [](const Matrixd& sigmas, - const Vectord<2 * States + 1>& Wm) -> StateVector { - return sigmas * Wm; - }; - m_meanFuncY = [](const Matrixd& sigmas, - const Vectord<2 * States + 1>& Wc) -> OutputVector { - return sigmas * Wc; - }; - m_residualFuncX = [](const StateVector& a, - const StateVector& b) -> StateVector { return a - b; }; - m_residualFuncY = [](const OutputVector& a, - const OutputVector& b) -> OutputVector { return a - b; }; - m_addFuncX = [](const StateVector& a, const StateVector& b) -> StateVector { - return a + b; - }; - m_dt = dt; - - Reset(); -} - -template -UnscentedKalmanFilter::UnscentedKalmanFilter( - std::function f, - std::function h, - const StateArray& stateStdDevs, const OutputArray& measurementStdDevs, - std::function&, - const Vectord<2 * States + 1>&)> - meanFuncX, - std::function&, - const Vectord<2 * States + 1>&)> - meanFuncY, - std::function - residualFuncX, - std::function - residualFuncY, - std::function addFuncX, - units::second_t dt) - : m_f(std::move(f)), - m_h(std::move(h)), - m_meanFuncX(std::move(meanFuncX)), - m_meanFuncY(std::move(meanFuncY)), - m_residualFuncX(std::move(residualFuncX)), - m_residualFuncY(std::move(residualFuncY)), - m_addFuncX(std::move(addFuncX)) { - m_contQ = MakeCovMatrix(stateStdDevs); - m_contR = MakeCovMatrix(measurementStdDevs); - m_dt = dt; - - Reset(); -} - -template -void UnscentedKalmanFilter::Predict( - const InputVector& u, units::second_t dt) { - m_dt = dt; - - // Discretize Q before projecting mean and covariance forward - StateMatrix contA = - NumericalJacobianX(m_f, m_xHat, u); - StateMatrix discA; - StateMatrix discQ; - DiscretizeAQ(contA, m_contQ, m_dt, &discA, &discQ); - Eigen::internal::llt_inplace::blocked(discQ); - - Matrixd sigmas = - m_pts.SquareRootSigmaPoints(m_xHat, m_S); - - for (int i = 0; i < m_pts.NumSigmas(); ++i) { - StateVector x = sigmas.template block(0, i); - m_sigmasF.template block(0, i) = RK4(m_f, x, u, dt); - } - - auto [xHat, S] = SquareRootUnscentedTransform( - m_sigmasF, m_pts.Wm(), m_pts.Wc(), m_meanFuncX, m_residualFuncX, - discQ.template triangularView()); - m_xHat = xHat; - m_S = S; -} - -template -template -void UnscentedKalmanFilter::Correct( - const InputVector& u, const Vectord& y, - std::function(const StateVector&, const InputVector&)> h, - const Matrixd& R) { - auto meanFuncY = [](const Matrixd& sigmas, - const Vectord<2 * States + 1>& Wc) -> Vectord { - return sigmas * Wc; - }; - auto residualFuncX = [](const StateVector& a, - const StateVector& b) -> StateVector { - return a - b; - }; - auto residualFuncY = [](const Vectord& a, - const Vectord& b) -> Vectord { - return a - b; - }; - auto addFuncX = [](const StateVector& a, - const StateVector& b) -> StateVector { return a + b; }; - Correct(u, y, std::move(h), R, std::move(meanFuncY), - std::move(residualFuncY), std::move(residualFuncX), - std::move(addFuncX)); -} - -template -template -void UnscentedKalmanFilter::Correct( - const InputVector& u, const Vectord& y, - std::function(const StateVector&, const InputVector&)> h, - const Matrixd& R, - std::function(const Matrixd&, - const Vectord<2 * States + 1>&)> - meanFuncY, - std::function(const Vectord&, const Vectord&)> - residualFuncY, - std::function - residualFuncX, - std::function - addFuncX) { - Matrixd discR = DiscretizeR(R, m_dt); - Eigen::internal::llt_inplace::blocked(discR); - - // Transform sigma points into measurement space - Matrixd sigmasH; - Matrixd sigmas = - m_pts.SquareRootSigmaPoints(m_xHat, m_S); - for (int i = 0; i < m_pts.NumSigmas(); ++i) { - sigmasH.template block(0, i) = - h(sigmas.template block(0, i), u); - } - - // Mean and covariance of prediction passed through UT - auto [yHat, Sy] = SquareRootUnscentedTransform( - sigmasH, m_pts.Wm(), m_pts.Wc(), meanFuncY, residualFuncY, - discR.template triangularView()); - - // Compute cross covariance of the state and the measurements - Matrixd Pxy; - Pxy.setZero(); - for (int i = 0; i < m_pts.NumSigmas(); ++i) { - // Pxy += (sigmas_f[:, i] - x̂)(sigmas_h[:, i] - ŷ)ᵀ W_c[i] - Pxy += m_pts.Wc(i) * - (residualFuncX(m_sigmasF.template block(0, i), m_xHat)) * - (residualFuncY(sigmasH.template block(0, i), yHat)) - .transpose(); - } - - // K = (P_{xy} / S_yᵀ) / S_y - // K = (S_y \ P_{xy}ᵀ)ᵀ / S_y - // K = (S_yᵀ \ (S_y \ P_{xy}ᵀ))ᵀ - Matrixd K = - Sy.transpose() - .fullPivHouseholderQr() - .solve(Sy.fullPivHouseholderQr().solve(Pxy.transpose())) - .transpose(); - - // x̂ₖ₊₁⁺ = x̂ₖ₊₁⁻ + K(y − ŷ) - m_xHat = addFuncX(m_xHat, K * residualFuncY(y, yHat)); - - Matrixd U = K * Sy; - for (int i = 0; i < Rows; i++) { - Eigen::internal::llt_inplace::rankUpdate( - m_S, U.template block(0, i), -1); - } -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/geometry/Pose2d.h b/wpimath/src/main/native/include/frc/geometry/Pose2d.h index 7f8f47cafe3..3a267e8cf08 100644 --- a/wpimath/src/main/native/include/frc/geometry/Pose2d.h +++ b/wpimath/src/main/native/include/frc/geometry/Pose2d.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -14,6 +15,7 @@ #include "frc/geometry/Transform2d.h" #include "frc/geometry/Translation2d.h" #include "frc/geometry/Twist2d.h" +#include "units/length.h" namespace frc { @@ -33,7 +35,9 @@ class WPILIB_DLLEXPORT Pose2d { * @param translation The translational component of the pose. * @param rotation The rotational component of the pose. */ - constexpr Pose2d(Translation2d translation, Rotation2d rotation); + constexpr Pose2d(Translation2d translation, Rotation2d rotation) + : m_translation{std::move(translation)}, + m_rotation{std::move(rotation)} {} /** * Constructs a pose with x and y translations instead of a separate @@ -43,7 +47,8 @@ class WPILIB_DLLEXPORT Pose2d { * @param y The y component of the translational component of the pose. * @param rotation The rotational component of the pose. */ - constexpr Pose2d(units::meter_t x, units::meter_t y, Rotation2d rotation); + constexpr Pose2d(units::meter_t x, units::meter_t y, Rotation2d rotation) + : m_translation{x, y}, m_rotation{std::move(rotation)} {} /** * Transforms the pose by the given transformation and returns the new @@ -59,7 +64,9 @@ class WPILIB_DLLEXPORT Pose2d { * * @return The transformed pose. */ - constexpr Pose2d operator+(const Transform2d& other) const; + constexpr Pose2d operator+(const Transform2d& other) const { + return TransformBy(other); + } /** * Returns the Transform2d that maps the one pose to another. @@ -109,7 +116,9 @@ class WPILIB_DLLEXPORT Pose2d { * * @return The new scaled Pose2d. */ - constexpr Pose2d operator*(double scalar) const; + constexpr Pose2d operator*(double scalar) const { + return Pose2d{m_translation * scalar, m_rotation * scalar}; + } /** * Divides the current pose by a scalar. @@ -118,7 +127,9 @@ class WPILIB_DLLEXPORT Pose2d { * * @return The new scaled Pose2d. */ - constexpr Pose2d operator/(double scalar) const; + constexpr Pose2d operator/(double scalar) const { + return *this * (1.0 / scalar); + } /** * Rotates the pose around the origin and returns the new pose. @@ -127,7 +138,9 @@ class WPILIB_DLLEXPORT Pose2d { * * @return The rotated pose. */ - constexpr Pose2d RotateBy(const Rotation2d& other) const; + constexpr Pose2d RotateBy(const Rotation2d& other) const { + return {m_translation.RotateBy(other), m_rotation.RotateBy(other)}; + } /** * Transforms the pose by the given transformation and returns the new pose. @@ -137,7 +150,10 @@ class WPILIB_DLLEXPORT Pose2d { * * @return The transformed pose. */ - constexpr Pose2d TransformBy(const Transform2d& other) const; + constexpr Pose2d TransformBy(const Transform2d& other) const { + return {m_translation + (other.Translation().RotateBy(m_rotation)), + other.Rotation() + m_rotation}; + } /** * Returns the current pose relative to the given pose. @@ -217,4 +233,3 @@ void from_json(const wpi::json& json, Pose2d& pose); #include "frc/geometry/proto/Pose2dProto.h" #endif #include "frc/geometry/struct/Pose2dStruct.h" -#include "frc/geometry/Pose2d.inc" diff --git a/wpimath/src/main/native/include/frc/geometry/Pose2d.inc b/wpimath/src/main/native/include/frc/geometry/Pose2d.inc deleted file mode 100644 index 559a0034e80..00000000000 --- a/wpimath/src/main/native/include/frc/geometry/Pose2d.inc +++ /dev/null @@ -1,43 +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 - -#include "frc/geometry/Pose2d.h" -#include "frc/geometry/Rotation2d.h" -#include "units/length.h" - -namespace frc { - -constexpr Pose2d::Pose2d(Translation2d translation, Rotation2d rotation) - : m_translation{std::move(translation)}, m_rotation{std::move(rotation)} {} - -constexpr Pose2d::Pose2d(units::meter_t x, units::meter_t y, - Rotation2d rotation) - : m_translation{x, y}, m_rotation{std::move(rotation)} {} - -constexpr Pose2d Pose2d::operator+(const Transform2d& other) const { - return TransformBy(other); -} - -constexpr Pose2d Pose2d::operator*(double scalar) const { - return Pose2d{m_translation * scalar, m_rotation * scalar}; -} - -constexpr Pose2d Pose2d::operator/(double scalar) const { - return *this * (1.0 / scalar); -} - -constexpr Pose2d Pose2d::RotateBy(const Rotation2d& other) const { - return {m_translation.RotateBy(other), m_rotation.RotateBy(other)}; -} - -constexpr Pose2d Pose2d::TransformBy(const Transform2d& other) const { - return {m_translation + (other.Translation().RotateBy(m_rotation)), - other.Rotation() + m_rotation}; -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/geometry/Rotation2d.h b/wpimath/src/main/native/include/frc/geometry/Rotation2d.h index 4e5357e9bb8..d35dc8330c0 100644 --- a/wpimath/src/main/native/include/frc/geometry/Rotation2d.h +++ b/wpimath/src/main/native/include/frc/geometry/Rotation2d.h @@ -4,10 +4,15 @@ #pragma once +#include + +#include +#include #include #include #include "units/angle.h" +#include "wpimath/MathShared.h" namespace frc { @@ -32,7 +37,10 @@ class WPILIB_DLLEXPORT Rotation2d { * * @param value The value of the angle. */ - constexpr Rotation2d(units::angle_unit auto value); // NOLINT + constexpr Rotation2d(units::angle_unit auto value) // NOLINT + : m_value{value}, + m_cos{gcem::cos(value.template convert().value())}, + m_sin{gcem::sin(value.template convert().value())} {} /** * Constructs a Rotation2d with the given x and y (cosine and sine) @@ -41,7 +49,22 @@ class WPILIB_DLLEXPORT Rotation2d { * @param x The x component or cosine of the rotation. * @param y The y component or sine of the rotation. */ - constexpr Rotation2d(double x, double y); + constexpr Rotation2d(double x, double y) { + double magnitude = gcem::hypot(x, y); + if (magnitude > 1e-6) { + m_sin = y / magnitude; + m_cos = x / magnitude; + } else { + m_sin = 0.0; + m_cos = 1.0; + if (!std::is_constant_evaluated()) { + wpi::math::MathSharedStore::ReportError( + "x and y components of Rotation2d are zero\n{}", + wpi::GetStackTrace(1)); + } + } + m_value = units::radian_t{gcem::atan2(m_sin, m_cos)}; + } /** * Adds two rotations together, with the result being bounded between -pi and @@ -54,7 +77,9 @@ class WPILIB_DLLEXPORT Rotation2d { * * @return The sum of the two rotations. */ - constexpr Rotation2d operator+(const Rotation2d& other) const; + constexpr Rotation2d operator+(const Rotation2d& other) const { + return RotateBy(other); + } /** * Subtracts the new rotation from the current rotation and returns the new @@ -67,7 +92,9 @@ class WPILIB_DLLEXPORT Rotation2d { * * @return The difference between the two rotations. */ - constexpr Rotation2d operator-(const Rotation2d& other) const; + constexpr Rotation2d operator-(const Rotation2d& other) const { + return *this + -other; + } /** * Takes the inverse of the current rotation. This is simply the negative of @@ -75,7 +102,7 @@ class WPILIB_DLLEXPORT Rotation2d { * * @return The inverse of the current rotation. */ - constexpr Rotation2d operator-() const; + constexpr Rotation2d operator-() const { return Rotation2d{-m_value}; } /** * Multiplies the current rotation by a scalar. @@ -84,7 +111,9 @@ class WPILIB_DLLEXPORT Rotation2d { * * @return The new scaled Rotation2d. */ - constexpr Rotation2d operator*(double scalar) const; + constexpr Rotation2d operator*(double scalar) const { + return Rotation2d{m_value * scalar}; + } /** * Divides the current rotation by a scalar. @@ -93,7 +122,9 @@ class WPILIB_DLLEXPORT Rotation2d { * * @return The new scaled Rotation2d. */ - constexpr Rotation2d operator/(double scalar) const; + constexpr Rotation2d operator/(double scalar) const { + return *this * (1.0 / scalar); + } /** * Checks equality between this Rotation2d and another object. @@ -101,7 +132,9 @@ class WPILIB_DLLEXPORT Rotation2d { * @param other The other object. * @return Whether the two objects are equal. */ - constexpr bool operator==(const Rotation2d& other) const; + constexpr bool operator==(const Rotation2d& other) const { + return gcem::hypot(Cos() - other.Cos(), Sin() - other.Sin()) < 1E-9; + } /** * Adds the new rotation to the current rotation using a rotation matrix. @@ -116,7 +149,10 @@ class WPILIB_DLLEXPORT Rotation2d { * * @return The new rotated Rotation2d. */ - constexpr Rotation2d RotateBy(const Rotation2d& other) const; + constexpr Rotation2d RotateBy(const Rotation2d& other) const { + return {Cos() * other.Cos() - Sin() * other.Sin(), + Cos() * other.Sin() + Sin() * other.Cos()}; + } /** * Returns the radian value of the rotation. @@ -173,4 +209,3 @@ void from_json(const wpi::json& json, Rotation2d& rotation); #include "frc/geometry/proto/Rotation2dProto.h" #endif #include "frc/geometry/struct/Rotation2dStruct.h" -#include "frc/geometry/Rotation2d.inc" diff --git a/wpimath/src/main/native/include/frc/geometry/Rotation2d.inc b/wpimath/src/main/native/include/frc/geometry/Rotation2d.inc deleted file mode 100644 index 740aaf0090d..00000000000 --- a/wpimath/src/main/native/include/frc/geometry/Rotation2d.inc +++ /dev/null @@ -1,70 +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 -#include - -#include -#include - -#include "frc/geometry/Rotation2d.h" -#include "units/angle.h" -#include "wpimath/MathShared.h" - -namespace frc { - -constexpr Rotation2d::Rotation2d(units::angle_unit auto value) - : m_value{value}, - m_cos{gcem::cos(value.template convert().value())}, - m_sin{gcem::sin(value.template convert().value())} {} - -constexpr Rotation2d::Rotation2d(double x, double y) { - double magnitude = gcem::hypot(x, y); - if (magnitude > 1e-6) { - m_sin = y / magnitude; - m_cos = x / magnitude; - } else { - m_sin = 0.0; - m_cos = 1.0; - if (!std::is_constant_evaluated()) { - wpi::math::MathSharedStore::ReportError( - "x and y components of Rotation2d are zero\n{}", - wpi::GetStackTrace(1)); - } - } - m_value = units::radian_t{gcem::atan2(m_sin, m_cos)}; -} - -constexpr Rotation2d Rotation2d::operator-() const { - return Rotation2d{-m_value}; -} - -constexpr Rotation2d Rotation2d::operator*(double scalar) const { - return Rotation2d{m_value * scalar}; -} - -constexpr Rotation2d Rotation2d::operator+(const Rotation2d& other) const { - return RotateBy(other); -} - -constexpr Rotation2d Rotation2d::operator-(const Rotation2d& other) const { - return *this + -other; -} - -constexpr Rotation2d Rotation2d::operator/(double scalar) const { - return *this * (1.0 / scalar); -} - -constexpr bool Rotation2d::operator==(const Rotation2d& other) const { - return gcem::hypot(Cos() - other.Cos(), Sin() - other.Sin()) < 1E-9; -} - -constexpr Rotation2d Rotation2d::RotateBy(const Rotation2d& other) const { - return {Cos() * other.Cos() - Sin() * other.Sin(), - Cos() * other.Sin() + Sin() * other.Cos()}; -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/geometry/Transform2d.h b/wpimath/src/main/native/include/frc/geometry/Transform2d.h index af984eadb4a..35271056edb 100644 --- a/wpimath/src/main/native/include/frc/geometry/Transform2d.h +++ b/wpimath/src/main/native/include/frc/geometry/Transform2d.h @@ -4,8 +4,11 @@ #pragma once +#include + #include +#include "frc/geometry/Rotation2d.h" #include "frc/geometry/Translation2d.h" namespace frc { @@ -31,7 +34,9 @@ class WPILIB_DLLEXPORT Transform2d { * @param translation Translational component of the transform. * @param rotation Rotational component of the transform. */ - constexpr Transform2d(Translation2d translation, Rotation2d rotation); + constexpr Transform2d(Translation2d translation, Rotation2d rotation) + : m_translation{std::move(translation)}, + m_rotation{std::move(rotation)} {} /** * Constructs a transform with x and y translations instead of a separate @@ -41,8 +46,8 @@ class WPILIB_DLLEXPORT Transform2d { * @param y The y component of the translational component of the transform. * @param rotation The rotational component of the transform. */ - constexpr Transform2d(units::meter_t x, units::meter_t y, - Rotation2d rotation); + constexpr Transform2d(units::meter_t x, units::meter_t y, Rotation2d rotation) + : m_translation{x, y}, m_rotation{std::move(rotation)} {} /** * Constructs the identity transform -- maps an initial pose to itself. @@ -82,7 +87,12 @@ class WPILIB_DLLEXPORT Transform2d { * * @return The inverted transformation. */ - constexpr Transform2d Inverse() const; + constexpr Transform2d Inverse() const { + // We are rotating the difference between the translations + // using a clockwise rotation matrix. This transforms the global + // delta into a local delta (relative to the initial pose). + return Transform2d{(-Translation()).RotateBy(-Rotation()), -Rotation()}; + } /** * Multiplies the transform by the scalar. @@ -128,4 +138,3 @@ class WPILIB_DLLEXPORT Transform2d { #include "frc/geometry/proto/Transform2dProto.h" #endif #include "frc/geometry/struct/Transform2dStruct.h" -#include "frc/geometry/Transform2d.inc" diff --git a/wpimath/src/main/native/include/frc/geometry/Transform2d.inc b/wpimath/src/main/native/include/frc/geometry/Transform2d.inc deleted file mode 100644 index cc925148d45..00000000000 --- a/wpimath/src/main/native/include/frc/geometry/Transform2d.inc +++ /dev/null @@ -1,30 +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 - -#include "frc/geometry/Rotation2d.h" -#include "frc/geometry/Transform2d.h" -#include "frc/geometry/Translation2d.h" - -namespace frc { - -constexpr Transform2d::Transform2d(Translation2d translation, - Rotation2d rotation) - : m_translation{std::move(translation)}, m_rotation{std::move(rotation)} {} - -constexpr Transform2d::Transform2d(units::meter_t x, units::meter_t y, - Rotation2d rotation) - : m_translation{x, y}, m_rotation{std::move(rotation)} {} - -constexpr Transform2d Transform2d::Inverse() const { - // We are rotating the difference between the translations - // using a clockwise rotation matrix. This transforms the global - // delta into a local delta (relative to the initial pose). - return Transform2d{(-Translation()).RotateBy(-Rotation()), -Rotation()}; -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/geometry/Translation2d.h b/wpimath/src/main/native/include/frc/geometry/Translation2d.h index 5c91e9d8fde..2a82a69c57f 100644 --- a/wpimath/src/main/native/include/frc/geometry/Translation2d.h +++ b/wpimath/src/main/native/include/frc/geometry/Translation2d.h @@ -39,7 +39,8 @@ class WPILIB_DLLEXPORT Translation2d { * @param x The x component of the translation. * @param y The y component of the translation. */ - constexpr Translation2d(units::meter_t x, units::meter_t y); + constexpr Translation2d(units::meter_t x, units::meter_t y) + : m_x{x}, m_y{y} {} /** * Constructs a Translation2d with the provided distance and angle. This is @@ -48,7 +49,8 @@ class WPILIB_DLLEXPORT Translation2d { * @param distance The distance from the origin to the end of the translation. * @param angle The angle between the x-axis and the translation vector. */ - constexpr Translation2d(units::meter_t distance, const Rotation2d& angle); + constexpr Translation2d(units::meter_t distance, const Rotation2d& angle) + : m_x{distance * angle.Cos()}, m_y{distance * angle.Sin()} {} /** * Constructs a Translation2d from the provided translation vector's X and Y @@ -90,7 +92,9 @@ class WPILIB_DLLEXPORT Translation2d { * * @return A Vector representation of this translation. */ - constexpr Eigen::Vector2d ToVector() const; + constexpr Eigen::Vector2d ToVector() const { + return Eigen::Vector2d{{m_x.value(), m_y.value()}}; + } /** * Returns the norm, or distance from the origin to the translation. @@ -104,7 +108,9 @@ class WPILIB_DLLEXPORT Translation2d { * * @return The angle of the translation */ - constexpr Rotation2d Angle() const; + constexpr Rotation2d Angle() const { + return Rotation2d{m_x.value(), m_y.value()}; + } /** * Applies a rotation to the translation in 2D space. @@ -124,7 +130,10 @@ class WPILIB_DLLEXPORT Translation2d { * * @return The new rotated translation. */ - constexpr Translation2d RotateBy(const Rotation2d& other) const; + constexpr Translation2d RotateBy(const Rotation2d& other) const { + return {m_x * other.Cos() - m_y * other.Sin(), + m_x * other.Sin() + m_y * other.Cos()}; + } /** * Rotates this translation around another translation in 2D space. @@ -139,7 +148,12 @@ class WPILIB_DLLEXPORT Translation2d { * @return The new rotated translation. */ constexpr Translation2d RotateAround(const Translation2d& other, - const Rotation2d& rot) const; + const Rotation2d& rot) const { + return {(m_x - other.X()) * rot.Cos() - (m_y - other.Y()) * rot.Sin() + + other.X(), + (m_x - other.X()) * rot.Sin() + (m_y - other.Y()) * rot.Cos() + + other.Y()}; + } /** * Returns the sum of two translations in 2D space. @@ -151,7 +165,9 @@ class WPILIB_DLLEXPORT Translation2d { * * @return The sum of the translations. */ - constexpr Translation2d operator+(const Translation2d& other) const; + constexpr Translation2d operator+(const Translation2d& other) const { + return {X() + other.X(), Y() + other.Y()}; + } /** * Returns the difference between two translations. @@ -163,7 +179,9 @@ class WPILIB_DLLEXPORT Translation2d { * * @return The difference between the two translations. */ - constexpr Translation2d operator-(const Translation2d& other) const; + constexpr Translation2d operator-(const Translation2d& other) const { + return *this + -other; + } /** * Returns the inverse of the current translation. This is equivalent to @@ -172,7 +190,7 @@ class WPILIB_DLLEXPORT Translation2d { * * @return The inverse of the current translation. */ - constexpr Translation2d operator-() const; + constexpr Translation2d operator-() const { return {-m_x, -m_y}; } /** * Returns the translation multiplied by a scalar. @@ -183,7 +201,9 @@ class WPILIB_DLLEXPORT Translation2d { * * @return The scaled translation. */ - constexpr Translation2d operator*(double scalar) const; + constexpr Translation2d operator*(double scalar) const { + return {scalar * m_x, scalar * m_y}; + } /** * Returns the translation divided by a scalar. @@ -194,7 +214,9 @@ class WPILIB_DLLEXPORT Translation2d { * * @return The scaled translation. */ - constexpr Translation2d operator/(double scalar) const; + constexpr Translation2d operator/(double scalar) const { + return operator*(1.0 / scalar); + } /** * Checks equality between this Translation2d and another object. @@ -202,7 +224,10 @@ class WPILIB_DLLEXPORT Translation2d { * @param other The other object. * @return Whether the two objects are equal. */ - constexpr bool operator==(const Translation2d& other) const; + constexpr bool operator==(const Translation2d& other) const { + return units::math::abs(m_x - other.m_x) < 1E-9_m && + units::math::abs(m_y - other.m_y) < 1E-9_m; + } /** * Returns the nearest Translation2d from a collection of translations @@ -236,4 +261,3 @@ void from_json(const wpi::json& json, Translation2d& state); #include "frc/geometry/proto/Translation2dProto.h" #endif #include "frc/geometry/struct/Translation2dStruct.h" -#include "frc/geometry/Translation2d.inc" diff --git a/wpimath/src/main/native/include/frc/geometry/Translation2d.inc b/wpimath/src/main/native/include/frc/geometry/Translation2d.inc deleted file mode 100644 index 2d1160abb4b..00000000000 --- a/wpimath/src/main/native/include/frc/geometry/Translation2d.inc +++ /dev/null @@ -1,68 +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 "frc/geometry/Translation2d.h" -#include "units/length.h" -#include "units/math.h" - -namespace frc { - -constexpr Translation2d::Translation2d(units::meter_t x, units::meter_t y) - : m_x{x}, m_y{y} {} - -constexpr Translation2d::Translation2d(units::meter_t distance, - const Rotation2d& angle) - : m_x{distance * angle.Cos()}, m_y{distance * angle.Sin()} {} - -constexpr Eigen::Vector2d Translation2d::ToVector() const { - return Eigen::Vector2d{{m_x.value(), m_y.value()}}; -} - -constexpr Rotation2d Translation2d::Angle() const { - return Rotation2d{m_x.value(), m_y.value()}; -} - -constexpr Translation2d Translation2d::RotateBy(const Rotation2d& other) const { - return {m_x * other.Cos() - m_y * other.Sin(), - m_x * other.Sin() + m_y * other.Cos()}; -} - -constexpr Translation2d Translation2d::RotateAround( - const Translation2d& other, const Rotation2d& rot) const { - return { - (m_x - other.X()) * rot.Cos() - (m_y - other.Y()) * rot.Sin() + other.X(), - (m_x - other.X()) * rot.Sin() + (m_y - other.Y()) * rot.Cos() + - other.Y()}; -} - -constexpr Translation2d Translation2d::operator+( - const Translation2d& other) const { - return {X() + other.X(), Y() + other.Y()}; -} - -constexpr Translation2d Translation2d::operator-( - const Translation2d& other) const { - return *this + -other; -} - -constexpr Translation2d Translation2d::operator-() const { - return {-m_x, -m_y}; -} - -constexpr Translation2d Translation2d::operator*(double scalar) const { - return {scalar * m_x, scalar * m_y}; -} - -constexpr Translation2d Translation2d::operator/(double scalar) const { - return operator*(1.0 / scalar); -} - -constexpr bool Translation2d::operator==(const Translation2d& other) const { - return units::math::abs(m_x - other.m_x) < 1E-9_m && - units::math::abs(m_y - other.m_y) < 1E-9_m; -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/geometry/Translation3d.h b/wpimath/src/main/native/include/frc/geometry/Translation3d.h index 75e5bf3dcf3..9aa3f61c31e 100644 --- a/wpimath/src/main/native/include/frc/geometry/Translation3d.h +++ b/wpimath/src/main/native/include/frc/geometry/Translation3d.h @@ -11,6 +11,7 @@ #include "frc/geometry/Rotation3d.h" #include "frc/geometry/Translation2d.h" #include "units/length.h" +#include "units/math.h" namespace frc { @@ -37,7 +38,8 @@ class WPILIB_DLLEXPORT Translation3d { * @param y The y component of the translation. * @param z The z component of the translation. */ - constexpr Translation3d(units::meter_t x, units::meter_t y, units::meter_t z); + constexpr Translation3d(units::meter_t x, units::meter_t y, units::meter_t z) + : m_x{x}, m_y{y}, m_z{z} {} /** * Constructs a Translation3d with the provided distance and angle. This is @@ -46,7 +48,12 @@ class WPILIB_DLLEXPORT Translation3d { * @param distance The distance from the origin to the end of the translation. * @param angle The angle between the x-axis and the translation vector. */ - Translation3d(units::meter_t distance, const Rotation3d& angle); + Translation3d(units::meter_t distance, const Rotation3d& angle) { + auto rectangular = Translation3d{distance, 0_m, 0_m}.RotateBy(angle); + m_x = rectangular.X(); + m_y = rectangular.Y(); + m_z = rectangular.Z(); + } /** * Constructs a Translation3d from the provided translation vector's X, Y, and @@ -54,7 +61,10 @@ class WPILIB_DLLEXPORT Translation3d { * * @param vector The translation vector to represent. */ - explicit Translation3d(const Eigen::Vector3d& vector); + explicit Translation3d(const Eigen::Vector3d& vector) + : m_x{units::meter_t{vector.x()}}, + m_y{units::meter_t{vector.y()}}, + m_z{units::meter_t{vector.z()}} {} /** * Calculates the distance between two translations in 3D space. @@ -66,7 +76,11 @@ class WPILIB_DLLEXPORT Translation3d { * * @return The distance between the two translations. */ - units::meter_t Distance(const Translation3d& other) const; + units::meter_t Distance(const Translation3d& other) const { + return units::math::sqrt(units::math::pow<2>(other.m_x - m_x) + + units::math::pow<2>(other.m_y - m_y) + + units::math::pow<2>(other.m_z - m_z)); + } /** * Returns the X component of the translation. @@ -94,14 +108,18 @@ class WPILIB_DLLEXPORT Translation3d { * * @return A Vector representation of this translation. */ - constexpr Eigen::Vector3d ToVector() const; + constexpr Eigen::Vector3d ToVector() const { + return Eigen::Vector3d{{m_x.value(), m_y.value(), m_z.value()}}; + } /** * Returns the norm, or distance from the origin to the translation. * * @return The norm of the translation. */ - units::meter_t Norm() const; + units::meter_t Norm() const { + return units::math::sqrt(m_x * m_x + m_y * m_y + m_z * m_z); + } /** * Applies a rotation to the translation in 3D space. @@ -113,13 +131,20 @@ class WPILIB_DLLEXPORT Translation3d { * * @return The new rotated translation. */ - Translation3d RotateBy(const Rotation3d& other) const; + Translation3d RotateBy(const Rotation3d& other) const { + Quaternion p{0.0, m_x.value(), m_y.value(), m_z.value()}; + auto qprime = other.GetQuaternion() * p * other.GetQuaternion().Inverse(); + return Translation3d{units::meter_t{qprime.X()}, units::meter_t{qprime.Y()}, + units::meter_t{qprime.Z()}}; + } /** * Returns a Translation2d representing this Translation3d projected into the * X-Y plane. */ - constexpr Translation2d ToTranslation2d() const; + constexpr Translation2d ToTranslation2d() const { + return Translation2d{m_x, m_y}; + } /** * Returns the sum of two translations in 3D space. @@ -131,7 +156,9 @@ class WPILIB_DLLEXPORT Translation3d { * * @return The sum of the translations. */ - constexpr Translation3d operator+(const Translation3d& other) const; + constexpr Translation3d operator+(const Translation3d& other) const { + return {X() + other.X(), Y() + other.Y(), Z() + other.Z()}; + } /** * Returns the difference between two translations. @@ -143,7 +170,9 @@ class WPILIB_DLLEXPORT Translation3d { * * @return The difference between the two translations. */ - constexpr Translation3d operator-(const Translation3d& other) const; + constexpr Translation3d operator-(const Translation3d& other) const { + return operator+(-other); + } /** * Returns the inverse of the current translation. This is equivalent to @@ -151,7 +180,7 @@ class WPILIB_DLLEXPORT Translation3d { * * @return The inverse of the current translation. */ - constexpr Translation3d operator-() const; + constexpr Translation3d operator-() const { return {-m_x, -m_y, -m_z}; } /** * Returns the translation multiplied by a scalar. @@ -163,7 +192,9 @@ class WPILIB_DLLEXPORT Translation3d { * * @return The scaled translation. */ - constexpr Translation3d operator*(double scalar) const; + constexpr Translation3d operator*(double scalar) const { + return {scalar * m_x, scalar * m_y, scalar * m_z}; + } /** * Returns the translation divided by a scalar. @@ -175,7 +206,9 @@ class WPILIB_DLLEXPORT Translation3d { * * @return The scaled translation. */ - constexpr Translation3d operator/(double scalar) const; + constexpr Translation3d operator/(double scalar) const { + return operator*(1.0 / scalar); + } /** * Checks equality between this Translation3d and another object. @@ -183,7 +216,11 @@ class WPILIB_DLLEXPORT Translation3d { * @param other The other object. * @return Whether the two objects are equal. */ - bool operator==(const Translation3d& other) const; + constexpr bool operator==(const Translation3d& other) const { + return units::math::abs(m_x - other.m_x) < 1E-9_m && + units::math::abs(m_y - other.m_y) < 1E-9_m && + units::math::abs(m_z - other.m_z) < 1E-9_m; + } private: units::meter_t m_x = 0_m; @@ -203,4 +240,3 @@ void from_json(const wpi::json& json, Translation3d& state); #include "frc/geometry/proto/Translation3dProto.h" #endif #include "frc/geometry/struct/Translation3dStruct.h" -#include "frc/geometry/Translation3d.inc" diff --git a/wpimath/src/main/native/include/frc/geometry/Translation3d.inc b/wpimath/src/main/native/include/frc/geometry/Translation3d.inc deleted file mode 100644 index 19268e6cee2..00000000000 --- a/wpimath/src/main/native/include/frc/geometry/Translation3d.inc +++ /dev/null @@ -1,48 +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 "frc/geometry/Translation2d.h" -#include "frc/geometry/Translation3d.h" -#include "units/length.h" -#include "units/math.h" - -namespace frc { - -constexpr Translation3d::Translation3d(units::meter_t x, units::meter_t y, - units::meter_t z) - : m_x{x}, m_y{y}, m_z{z} {} - -constexpr Translation2d Translation3d::ToTranslation2d() const { - return Translation2d{m_x, m_y}; -} - -constexpr Eigen::Vector3d Translation3d::ToVector() const { - return Eigen::Vector3d{{m_x.value(), m_y.value(), m_z.value()}}; -} - -constexpr Translation3d Translation3d::operator+( - const Translation3d& other) const { - return {X() + other.X(), Y() + other.Y(), Z() + other.Z()}; -} - -constexpr Translation3d Translation3d::operator-( - const Translation3d& other) const { - return operator+(-other); -} - -constexpr Translation3d Translation3d::operator-() const { - return {-m_x, -m_y, -m_z}; -} - -constexpr Translation3d Translation3d::operator*(double scalar) const { - return {scalar * m_x, scalar * m_y, scalar * m_z}; -} - -constexpr Translation3d Translation3d::operator/(double scalar) const { - return operator*(1.0 / scalar); -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/kinematics/Odometry.h b/wpimath/src/main/native/include/frc/kinematics/Odometry.h index e5a8e0f618e..c73eed22482 100644 --- a/wpimath/src/main/native/include/frc/kinematics/Odometry.h +++ b/wpimath/src/main/native/include/frc/kinematics/Odometry.h @@ -12,6 +12,7 @@ #include "frc/kinematics/Kinematics.h" namespace frc { + /** * Class for odometry. Robot code should not use this directly- Instead, use the * particular type for your drivetrain (e.g., DifferentialDriveOdometry). @@ -39,7 +40,13 @@ class WPILIB_DLLEXPORT Odometry { explicit Odometry(const Kinematics& kinematics, const Rotation2d& gyroAngle, const WheelPositions& wheelPositions, - const Pose2d& initialPose = Pose2d{}); + const Pose2d& initialPose = Pose2d{}) + : m_kinematics(kinematics), + m_pose(initialPose), + m_previousWheelPositions(wheelPositions) { + m_previousAngle = m_pose.Rotation(); + m_gyroOffset = m_pose.Rotation() - gyroAngle; + } /** * Resets the robot's position on the field. @@ -108,7 +115,21 @@ class WPILIB_DLLEXPORT Odometry { * @return The new pose of the robot. */ const Pose2d& Update(const Rotation2d& gyroAngle, - const WheelPositions& wheelPositions); + const WheelPositions& wheelPositions) { + auto angle = gyroAngle + m_gyroOffset; + + auto twist = + m_kinematics.ToTwist2d(m_previousWheelPositions, wheelPositions); + twist.dtheta = (angle - m_previousAngle).Radians(); + + auto newPose = m_pose.Exp(twist); + + m_previousAngle = angle; + m_previousWheelPositions = wheelPositions; + m_pose = {newPose.Translation(), angle}; + + return m_pose; + } private: const Kinematics& m_kinematics; @@ -118,6 +139,5 @@ class WPILIB_DLLEXPORT Odometry { Rotation2d m_previousAngle; Rotation2d m_gyroOffset; }; -} // namespace frc -#include "Odometry.inc" +} // namespace frc diff --git a/wpimath/src/main/native/include/frc/kinematics/Odometry.inc b/wpimath/src/main/native/include/frc/kinematics/Odometry.inc deleted file mode 100644 index 384a2ddebc6..00000000000 --- a/wpimath/src/main/native/include/frc/kinematics/Odometry.inc +++ /dev/null @@ -1,38 +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 "frc/kinematics/Odometry.h" - -namespace frc { -template -Odometry::Odometry( - const Kinematics& kinematics, - const Rotation2d& gyroAngle, const WheelPositions& wheelPositions, - const Pose2d& initialPose) - : m_kinematics(kinematics), - m_pose(initialPose), - m_previousWheelPositions(wheelPositions) { - m_previousAngle = m_pose.Rotation(); - m_gyroOffset = m_pose.Rotation() - gyroAngle; -} - -template -const Pose2d& Odometry::Update( - const Rotation2d& gyroAngle, const WheelPositions& wheelPositions) { - auto angle = gyroAngle + m_gyroOffset; - - auto twist = m_kinematics.ToTwist2d(m_previousWheelPositions, wheelPositions); - twist.dtheta = (angle - m_previousAngle).Radians(); - - auto newPose = m_pose.Exp(twist); - - m_previousAngle = angle; - m_previousWheelPositions = wheelPositions; - m_pose = {newPose.Translation(), angle}; - - return m_pose; -} -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/kinematics/SwerveDriveKinematics.h b/wpimath/src/main/native/include/frc/kinematics/SwerveDriveKinematics.h index 98eea68e306..aecc3306d55 100644 --- a/wpimath/src/main/native/include/frc/kinematics/SwerveDriveKinematics.h +++ b/wpimath/src/main/native/include/frc/kinematics/SwerveDriveKinematics.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -19,6 +20,7 @@ #include "frc/kinematics/Kinematics.h" #include "frc/kinematics/SwerveModulePosition.h" #include "frc/kinematics/SwerveModuleState.h" +#include "units/math.h" #include "units/velocity.h" #include "wpimath/MathShared.h" @@ -116,7 +118,11 @@ class SwerveDriveKinematics * @param moduleHeadings The swerve module headings. The order of the module * headings should be same as passed into the constructor of this class. */ - void ResetHeadings(wpi::array moduleHeadings); + void ResetHeadings(wpi::array moduleHeadings) { + for (size_t i = 0; i < NumModules; i++) { + m_moduleHeadings[i] = moduleHeadings[i]; + } + } /** * Performs inverse kinematics to return the module states from a desired @@ -151,7 +157,52 @@ class SwerveDriveKinematics */ wpi::array ToSwerveModuleStates( const ChassisSpeeds& chassisSpeeds, - const Translation2d& centerOfRotation = Translation2d{}) const; + const Translation2d& centerOfRotation = Translation2d{}) const { + wpi::array moduleStates(wpi::empty_array); + + if (chassisSpeeds.vx == 0_mps && chassisSpeeds.vy == 0_mps && + chassisSpeeds.omega == 0_rad_per_s) { + for (size_t i = 0; i < NumModules; i++) { + moduleStates[i] = {0_mps, m_moduleHeadings[i]}; + } + + return moduleStates; + } + + // We have a new center of rotation. We need to compute the matrix again. + if (centerOfRotation != m_previousCoR) { + for (size_t i = 0; i < NumModules; i++) { + // clang-format off + m_inverseKinematics.template block<2, 3>(i * 2, 0) = + Matrixd<2, 3>{ + {1, 0, (-m_modules[i].Y() + centerOfRotation.Y()).value()}, + {0, 1, (+m_modules[i].X() - centerOfRotation.X()).value()}}; + // clang-format on + } + m_previousCoR = centerOfRotation; + } + + Eigen::Vector3d chassisSpeedsVector{chassisSpeeds.vx.value(), + chassisSpeeds.vy.value(), + chassisSpeeds.omega.value()}; + + Matrixd moduleStateMatrix = + m_inverseKinematics * chassisSpeedsVector; + + for (size_t i = 0; i < NumModules; i++) { + units::meters_per_second_t x{moduleStateMatrix(i * 2, 0)}; + units::meters_per_second_t y{moduleStateMatrix(i * 2 + 1, 0)}; + + auto speed = units::math::hypot(x, y); + auto rotation = speed > 1e-6_mps ? Rotation2d{x.value(), y.value()} + : m_moduleHeadings[i]; + + moduleStates[i] = {speed, rotation}; + m_moduleHeadings[i] = rotation; + } + + return moduleStates; + } wpi::array ToWheelSpeeds( const ChassisSpeeds& chassisSpeeds) const override { @@ -191,7 +242,23 @@ class SwerveDriveKinematics * @return The resulting chassis speed. */ ChassisSpeeds ToChassisSpeeds(const wpi::array& - moduleStates) const override; + moduleStates) const override { + Matrixd moduleStateMatrix; + + for (size_t i = 0; i < NumModules; ++i) { + SwerveModuleState module = moduleStates[i]; + moduleStateMatrix(i * 2, 0) = module.speed.value() * module.angle.Cos(); + moduleStateMatrix(i * 2 + 1, 0) = + module.speed.value() * module.angle.Sin(); + } + + Eigen::Vector3d chassisSpeedsVector = + m_forwardKinematics.solve(moduleStateMatrix); + + return {units::meters_per_second_t{chassisSpeedsVector(0)}, + units::meters_per_second_t{chassisSpeedsVector(1)}, + units::radians_per_second_t{chassisSpeedsVector(2)}}; + } /** * Performs forward kinematics to return the resulting Twist2d from the @@ -227,7 +294,24 @@ class SwerveDriveKinematics * @return The resulting Twist2d. */ Twist2d ToTwist2d( - wpi::array moduleDeltas) const; + wpi::array moduleDeltas) const { + Matrixd moduleDeltaMatrix; + + for (size_t i = 0; i < NumModules; ++i) { + SwerveModulePosition module = moduleDeltas[i]; + moduleDeltaMatrix(i * 2, 0) = + module.distance.value() * module.angle.Cos(); + moduleDeltaMatrix(i * 2 + 1, 0) = + module.distance.value() * module.angle.Sin(); + } + + Eigen::Vector3d chassisDeltaVector = + m_forwardKinematics.solve(moduleDeltaMatrix); + + return {units::meter_t{chassisDeltaVector(0)}, + units::meter_t{chassisDeltaVector(1)}, + units::radian_t{chassisDeltaVector(2)}}; + } Twist2d ToTwist2d( const wpi::array& start, @@ -257,7 +341,22 @@ class SwerveDriveKinematics */ static void DesaturateWheelSpeeds( wpi::array* moduleStates, - units::meters_per_second_t attainableMaxSpeed); + units::meters_per_second_t attainableMaxSpeed) { + auto& states = *moduleStates; + auto realMaxSpeed = + units::math::abs(std::max_element(states.begin(), states.end(), + [](const auto& a, const auto& b) { + return units::math::abs(a.speed) < + units::math::abs(b.speed); + }) + ->speed); + + if (realMaxSpeed > attainableMaxSpeed) { + for (auto& module : states) { + module.speed = module.speed / realMaxSpeed * attainableMaxSpeed; + } + } + } /** * Renormalizes the wheel speeds if any individual speed is above the @@ -285,7 +384,38 @@ class SwerveDriveKinematics ChassisSpeeds desiredChassisSpeed, units::meters_per_second_t attainableMaxModuleSpeed, units::meters_per_second_t attainableMaxRobotTranslationSpeed, - units::radians_per_second_t attainableMaxRobotRotationSpeed); + units::radians_per_second_t attainableMaxRobotRotationSpeed) { + auto& states = *moduleStates; + + auto realMaxSpeed = + units::math::abs(std::max_element(states.begin(), states.end(), + [](const auto& a, const auto& b) { + return units::math::abs(a.speed) < + units::math::abs(b.speed); + }) + ->speed); + + if (attainableMaxRobotTranslationSpeed == 0_mps || + attainableMaxRobotRotationSpeed == 0_rad_per_s || + realMaxSpeed == 0_mps) { + return; + } + + auto translationalK = + units::math::hypot(desiredChassisSpeed.vx, desiredChassisSpeed.vy) / + attainableMaxRobotTranslationSpeed; + + auto rotationalK = units::math::abs(desiredChassisSpeed.omega) / + attainableMaxRobotRotationSpeed; + + auto k = units::math::max(translationalK, rotationalK); + + auto scale = units::math::min(k * attainableMaxModuleSpeed / realMaxSpeed, + units::scalar_t{1}); + for (auto& module : states) { + module.speed = module.speed * scale; + } + } wpi::array Interpolate( const wpi::array& start, @@ -312,9 +442,11 @@ class SwerveDriveKinematics mutable Translation2d m_previousCoR; }; +template +SwerveDriveKinematics(ModuleTranslation, ModuleTranslations...) + -> SwerveDriveKinematics<1 + sizeof...(ModuleTranslations)>; + extern template class EXPORT_TEMPLATE_DECLARE(WPILIB_DLLEXPORT) SwerveDriveKinematics<4>; } // namespace frc - -#include "SwerveDriveKinematics.inc" diff --git a/wpimath/src/main/native/include/frc/kinematics/SwerveDriveKinematics.inc b/wpimath/src/main/native/include/frc/kinematics/SwerveDriveKinematics.inc deleted file mode 100644 index 8c5e18b3592..00000000000 --- a/wpimath/src/main/native/include/frc/kinematics/SwerveDriveKinematics.inc +++ /dev/null @@ -1,176 +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 -#include - -#include "frc/kinematics/ChassisSpeeds.h" -#include "frc/kinematics/SwerveDriveKinematics.h" -#include "units/math.h" - -namespace frc { - -template -SwerveDriveKinematics(ModuleTranslation, ModuleTranslations...) - -> SwerveDriveKinematics<1 + sizeof...(ModuleTranslations)>; - -template -void SwerveDriveKinematics::ResetHeadings( - wpi::array moduleHeadings) { - for (size_t i = 0; i < NumModules; i++) { - m_moduleHeadings[i] = moduleHeadings[i]; - } -} - -template -wpi::array -SwerveDriveKinematics::ToSwerveModuleStates( - const ChassisSpeeds& chassisSpeeds, - const Translation2d& centerOfRotation) const { - wpi::array moduleStates(wpi::empty_array); - - if (chassisSpeeds.vx == 0_mps && chassisSpeeds.vy == 0_mps && - chassisSpeeds.omega == 0_rad_per_s) { - for (size_t i = 0; i < NumModules; i++) { - moduleStates[i] = {0_mps, m_moduleHeadings[i]}; - } - - return moduleStates; - } - - // We have a new center of rotation. We need to compute the matrix again. - if (centerOfRotation != m_previousCoR) { - for (size_t i = 0; i < NumModules; i++) { - // clang-format off - m_inverseKinematics.template block<2, 3>(i * 2, 0) = - Matrixd<2, 3>{ - {1, 0, (-m_modules[i].Y() + centerOfRotation.Y()).value()}, - {0, 1, (+m_modules[i].X() - centerOfRotation.X()).value()}}; - // clang-format on - } - m_previousCoR = centerOfRotation; - } - - Eigen::Vector3d chassisSpeedsVector{chassisSpeeds.vx.value(), - chassisSpeeds.vy.value(), - chassisSpeeds.omega.value()}; - - Matrixd moduleStateMatrix = - m_inverseKinematics * chassisSpeedsVector; - - for (size_t i = 0; i < NumModules; i++) { - units::meters_per_second_t x{moduleStateMatrix(i * 2, 0)}; - units::meters_per_second_t y{moduleStateMatrix(i * 2 + 1, 0)}; - - auto speed = units::math::hypot(x, y); - auto rotation = speed > 1e-6_mps ? Rotation2d{x.value(), y.value()} - : m_moduleHeadings[i]; - - moduleStates[i] = {speed, rotation}; - m_moduleHeadings[i] = rotation; - } - - return moduleStates; -} - -template -ChassisSpeeds SwerveDriveKinematics::ToChassisSpeeds( - const wpi::array& moduleStates) const { - Matrixd moduleStateMatrix; - - for (size_t i = 0; i < NumModules; ++i) { - SwerveModuleState module = moduleStates[i]; - moduleStateMatrix(i * 2, 0) = module.speed.value() * module.angle.Cos(); - moduleStateMatrix(i * 2 + 1, 0) = module.speed.value() * module.angle.Sin(); - } - - Eigen::Vector3d chassisSpeedsVector = - m_forwardKinematics.solve(moduleStateMatrix); - - return {units::meters_per_second_t{chassisSpeedsVector(0)}, - units::meters_per_second_t{chassisSpeedsVector(1)}, - units::radians_per_second_t{chassisSpeedsVector(2)}}; -} - -template -Twist2d SwerveDriveKinematics::ToTwist2d( - wpi::array moduleDeltas) const { - Matrixd moduleDeltaMatrix; - - for (size_t i = 0; i < NumModules; ++i) { - SwerveModulePosition module = moduleDeltas[i]; - moduleDeltaMatrix(i * 2, 0) = module.distance.value() * module.angle.Cos(); - moduleDeltaMatrix(i * 2 + 1, 0) = - module.distance.value() * module.angle.Sin(); - } - - Eigen::Vector3d chassisDeltaVector = - m_forwardKinematics.solve(moduleDeltaMatrix); - - return {units::meter_t{chassisDeltaVector(0)}, - units::meter_t{chassisDeltaVector(1)}, - units::radian_t{chassisDeltaVector(2)}}; -} - -template -void SwerveDriveKinematics::DesaturateWheelSpeeds( - wpi::array* moduleStates, - units::meters_per_second_t attainableMaxSpeed) { - auto& states = *moduleStates; - auto realMaxSpeed = - units::math::abs(std::max_element(states.begin(), states.end(), - [](const auto& a, const auto& b) { - return units::math::abs(a.speed) < - units::math::abs(b.speed); - }) - ->speed); - - if (realMaxSpeed > attainableMaxSpeed) { - for (auto& module : states) { - module.speed = module.speed / realMaxSpeed * attainableMaxSpeed; - } - } -} - -template -void SwerveDriveKinematics::DesaturateWheelSpeeds( - wpi::array* moduleStates, - ChassisSpeeds desiredChassisSpeed, - units::meters_per_second_t attainableMaxModuleSpeed, - units::meters_per_second_t attainableMaxRobotTranslationSpeed, - units::radians_per_second_t attainableMaxRobotRotationSpeed) { - auto& states = *moduleStates; - - auto realMaxSpeed = - units::math::abs(std::max_element(states.begin(), states.end(), - [](const auto& a, const auto& b) { - return units::math::abs(a.speed) < - units::math::abs(b.speed); - }) - ->speed); - - if (attainableMaxRobotTranslationSpeed == 0_mps || - attainableMaxRobotRotationSpeed == 0_rad_per_s || realMaxSpeed == 0_mps) { - return; - } - - auto translationalK = - units::math::hypot(desiredChassisSpeed.vx, desiredChassisSpeed.vy) / - attainableMaxRobotTranslationSpeed; - - auto rotationalK = units::math::abs(desiredChassisSpeed.omega) / - attainableMaxRobotRotationSpeed; - - auto k = units::math::max(translationalK, rotationalK); - - auto scale = units::math::min(k * attainableMaxModuleSpeed / realMaxSpeed, - units::scalar_t{1}); - for (auto& module : states) { - module.speed = module.speed * scale; - } -} - -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/kinematics/SwerveDriveOdometry.h b/wpimath/src/main/native/include/frc/kinematics/SwerveDriveOdometry.h index 7c66977bb98..c00acd2e0da 100644 --- a/wpimath/src/main/native/include/frc/kinematics/SwerveDriveOdometry.h +++ b/wpimath/src/main/native/include/frc/kinematics/SwerveDriveOdometry.h @@ -4,7 +4,6 @@ #pragma once -#include #include #include @@ -16,7 +15,7 @@ #include "SwerveModulePosition.h" #include "SwerveModuleState.h" #include "frc/geometry/Pose2d.h" -#include "units/time.h" +#include "wpimath/MathShared.h" namespace frc { @@ -45,7 +44,14 @@ class SwerveDriveOdometry SwerveDriveOdometry( SwerveDriveKinematics kinematics, const Rotation2d& gyroAngle, const wpi::array& modulePositions, - const Pose2d& initialPose = Pose2d{}); + const Pose2d& initialPose = Pose2d{}) + : Odometry, + wpi::array>( + m_kinematicsImpl, gyroAngle, modulePositions, initialPose), + m_kinematicsImpl(kinematics) { + wpi::math::MathSharedStore::ReportUsage( + wpi::math::MathUsageId::kOdometry_SwerveDrive, 1); + } private: SwerveDriveKinematics m_kinematicsImpl; @@ -55,5 +61,3 @@ extern template class EXPORT_TEMPLATE_DECLARE(WPILIB_DLLEXPORT) SwerveDriveOdometry<4>; } // namespace frc - -#include "SwerveDriveOdometry.inc" diff --git a/wpimath/src/main/native/include/frc/kinematics/SwerveDriveOdometry.inc b/wpimath/src/main/native/include/frc/kinematics/SwerveDriveOdometry.inc deleted file mode 100644 index 2b047c21944..00000000000 --- a/wpimath/src/main/native/include/frc/kinematics/SwerveDriveOdometry.inc +++ /dev/null @@ -1,23 +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 "frc/kinematics/SwerveDriveOdometry.h" -#include "wpimath/MathShared.h" - -namespace frc { -template -SwerveDriveOdometry::SwerveDriveOdometry( - SwerveDriveKinematics kinematics, const Rotation2d& gyroAngle, - const wpi::array& modulePositions, - const Pose2d& initialPose) - : Odometry, - wpi::array>( - m_kinematicsImpl, gyroAngle, modulePositions, initialPose), - m_kinematicsImpl(kinematics) { - wpi::math::MathSharedStore::ReportUsage( - wpi::math::MathUsageId::kOdometry_SwerveDrive, 1); -} -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/kinematics/proto/SwerveDriveKinematicsProto.h b/wpimath/src/main/native/include/frc/kinematics/proto/SwerveDriveKinematicsProto.h index b84343459d9..d9fc19a2004 100644 --- a/wpimath/src/main/native/include/frc/kinematics/proto/SwerveDriveKinematicsProto.h +++ b/wpimath/src/main/native/include/frc/kinematics/proto/SwerveDriveKinematicsProto.h @@ -4,17 +4,39 @@ #pragma once +#include + +#include +#include #include #include "frc/kinematics/SwerveDriveKinematics.h" +#include "kinematics.pb.h" template struct wpi::Protobuf> { - static google::protobuf::Message* New(google::protobuf::Arena* arena); + static google::protobuf::Message* New(google::protobuf::Arena* arena) { + return wpi::CreateMessage(arena); + } + static frc::SwerveDriveKinematics Unpack( - const google::protobuf::Message& msg); + const google::protobuf::Message& msg) { + auto m = + static_cast(&msg); + if (m->modules_size() != NumModules) { + throw std::invalid_argument(fmt::format( + "Tried to unpack message with {} elements in modules into " + "SwerveDriveKinematics with {} modules", + m->modules_size(), NumModules)); + } + return frc::SwerveDriveKinematics{ + wpi::UnpackProtobufArray(m->modules())}; + } + static void Pack(google::protobuf::Message* msg, - const frc::SwerveDriveKinematics& value); + const frc::SwerveDriveKinematics& value) { + auto m = static_cast(msg); + wpi::PackProtobufArray(m->mutable_modules(), value.GetModules()); + } }; - -#include "frc/kinematics/proto/SwerveDriveKinematicsProto.inc" diff --git a/wpimath/src/main/native/include/frc/kinematics/proto/SwerveDriveKinematicsProto.inc b/wpimath/src/main/native/include/frc/kinematics/proto/SwerveDriveKinematicsProto.inc deleted file mode 100644 index 0a9925481d9..00000000000 --- a/wpimath/src/main/native/include/frc/kinematics/proto/SwerveDriveKinematicsProto.inc +++ /dev/null @@ -1,44 +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 - -#include -#include - -#include "frc/kinematics/proto/SwerveDriveKinematicsProto.h" -#include "kinematics.pb.h" - -template -google::protobuf::Message* -wpi::Protobuf>::New( - google::protobuf::Arena* arena) { - return wpi::CreateMessage(arena); -} - -template -frc::SwerveDriveKinematics -wpi::Protobuf>::Unpack( - const google::protobuf::Message& msg) { - auto m = static_cast(&msg); - if (m->modules_size() != NumModules) { - throw std::invalid_argument( - fmt::format("Tried to unpack message with {} elements in modules into " - "SwerveDriveKinematics with {} modules", - m->modules_size(), NumModules)); - } - return frc::SwerveDriveKinematics{ - wpi::UnpackProtobufArray(m->modules())}; -} - -template -void wpi::Protobuf>::Pack( - google::protobuf::Message* msg, - const frc::SwerveDriveKinematics& value) { - auto m = static_cast(msg); - wpi::PackProtobufArray(m->mutable_modules(), value.GetModules()); -} diff --git a/wpimath/src/main/native/include/frc/kinematics/struct/SwerveDriveKinematicsStruct.h b/wpimath/src/main/native/include/frc/kinematics/struct/SwerveDriveKinematicsStruct.h index 139b78dbdc0..b351fab26c7 100644 --- a/wpimath/src/main/native/include/frc/kinematics/struct/SwerveDriveKinematicsStruct.h +++ b/wpimath/src/main/native/include/frc/kinematics/struct/SwerveDriveKinematicsStruct.h @@ -24,9 +24,19 @@ struct wpi::Struct> { static constexpr std::string_view GetSchema() { return kSchema; } static frc::SwerveDriveKinematics Unpack( - std::span data); + std::span data) { + constexpr size_t kModulesOff = 0; + return frc::SwerveDriveKinematics{ + wpi::UnpackStructArray( + data)}; + } + static void Pack(std::span data, - const frc::SwerveDriveKinematics& value); + const frc::SwerveDriveKinematics& value) { + constexpr size_t kModulesOff = 0; + wpi::PackStructArray(data, value.GetModules()); + } + static void ForEachNested( std::invocable auto fn) { wpi::ForEachStructSchema(fn); @@ -37,5 +47,3 @@ static_assert(wpi::StructSerializable>); static_assert(wpi::HasNestedStruct>); static_assert(wpi::StructSerializable>); static_assert(wpi::HasNestedStruct>); - -#include "frc/kinematics/struct/SwerveDriveKinematicsStruct.inc" diff --git a/wpimath/src/main/native/include/frc/kinematics/struct/SwerveDriveKinematicsStruct.inc b/wpimath/src/main/native/include/frc/kinematics/struct/SwerveDriveKinematicsStruct.inc deleted file mode 100644 index 5e4dee13eeb..00000000000 --- a/wpimath/src/main/native/include/frc/kinematics/struct/SwerveDriveKinematicsStruct.inc +++ /dev/null @@ -1,25 +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 "frc/kinematics/struct/SwerveDriveKinematicsStruct.h" - -template -frc::SwerveDriveKinematics -wpi::Struct>::Unpack( - std::span data) { - constexpr size_t kModulesOff = 0; - return frc::SwerveDriveKinematics{ - wpi::UnpackStructArray( - data)}; -} - -template -void wpi::Struct>::Pack( - std::span data, - const frc::SwerveDriveKinematics& value) { - constexpr size_t kModulesOff = 0; - wpi::PackStructArray(data, value.GetModules()); -} diff --git a/wpimath/src/main/native/include/frc/proto/MatrixProto.h b/wpimath/src/main/native/include/frc/proto/MatrixProto.h index 1440c513c6e..8dc9285b3cb 100644 --- a/wpimath/src/main/native/include/frc/proto/MatrixProto.h +++ b/wpimath/src/main/native/include/frc/proto/MatrixProto.h @@ -4,19 +4,53 @@ #pragma once +#include + +#include +#include #include #include "frc/EigenCore.h" +#include "wpimath.pb.h" template requires(Cols != 1) struct wpi::Protobuf> { - static google::protobuf::Message* New(google::protobuf::Arena* arena); + static google::protobuf::Message* New(google::protobuf::Arena* arena) { + return wpi::CreateMessage(arena); + } + static frc::Matrixd Unpack( - const google::protobuf::Message& msg); + const google::protobuf::Message& msg) { + auto m = static_cast(&msg); + if (m->num_rows() != Rows || m->num_cols() != Cols) { + throw std::invalid_argument(fmt::format( + "Tried to unpack message with {} rows and {} columns into " + "Matrix with {} rows and {} columns", + m->num_rows(), m->num_cols(), Rows, Cols)); + } + if (m->data_size() != Rows * Cols) { + throw std::invalid_argument( + fmt::format("Tried to unpack message with {} elements in data into " + "Matrix with {} elements", + m->data_size(), Rows * Cols)); + } + frc::Matrixd mat; + for (int i = 0; i < Rows * Cols; i++) { + mat(i) = m->data(i); + } + return mat; + } + static void Pack( google::protobuf::Message* msg, - const frc::Matrixd& value); + const frc::Matrixd& value) { + auto m = static_cast(msg); + m->set_num_rows(Rows); + m->set_num_cols(Cols); + m->clear_data(); + for (int i = 0; i < Rows * Cols; i++) { + m->add_data(value(i)); + } + } }; - -#include "frc/proto/MatrixProto.inc" diff --git a/wpimath/src/main/native/include/frc/proto/MatrixProto.inc b/wpimath/src/main/native/include/frc/proto/MatrixProto.inc deleted file mode 100644 index 75370b64217..00000000000 --- a/wpimath/src/main/native/include/frc/proto/MatrixProto.inc +++ /dev/null @@ -1,60 +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 - -#include -#include - -#include "frc/proto/MatrixProto.h" -#include "wpimath.pb.h" - -template - requires(Cols != 1) -google::protobuf::Message* -wpi::Protobuf>::New( - google::protobuf::Arena* arena) { - return wpi::CreateMessage(arena); -} - -template - requires(Cols != 1) -frc::Matrixd -wpi::Protobuf>::Unpack( - const google::protobuf::Message& msg) { - auto m = static_cast(&msg); - if (m->num_rows() != Rows || m->num_cols() != Cols) { - throw std::invalid_argument( - fmt::format("Tried to unpack message with {} rows and {} columns into " - "Matrix with {} rows and {} columns", - m->num_rows(), m->num_cols(), Rows, Cols)); - } - if (m->data_size() != Rows * Cols) { - throw std::invalid_argument( - fmt::format("Tried to unpack message with {} elements in data into " - "Matrix with {} elements", - m->data_size(), Rows * Cols)); - } - frc::Matrixd mat; - for (int i = 0; i < Rows * Cols; i++) { - mat(i) = m->data(i); - } - return mat; -} - -template - requires(Cols != 1) -void wpi::Protobuf>::Pack( - google::protobuf::Message* msg, - const frc::Matrixd& value) { - auto m = static_cast(msg); - m->set_num_rows(Rows); - m->set_num_cols(Cols); - m->clear_data(); - for (int i = 0; i < Rows * Cols; i++) { - m->add_data(value(i)); - } -} diff --git a/wpimath/src/main/native/include/frc/proto/VectorProto.h b/wpimath/src/main/native/include/frc/proto/VectorProto.h index 654f31c0882..a982e19a70a 100644 --- a/wpimath/src/main/native/include/frc/proto/VectorProto.h +++ b/wpimath/src/main/native/include/frc/proto/VectorProto.h @@ -4,18 +4,44 @@ #pragma once +#include + +#include +#include #include #include "frc/EigenCore.h" +#include "wpimath.pb.h" template struct wpi::Protobuf> { - static google::protobuf::Message* New(google::protobuf::Arena* arena); + static google::protobuf::Message* New(google::protobuf::Arena* arena) { + return wpi::CreateMessage(arena); + } + static frc::Matrixd Unpack( - const google::protobuf::Message& msg); + const google::protobuf::Message& msg) { + auto m = static_cast(&msg); + if (m->rows_size() != Size) { + throw std::invalid_argument( + fmt::format("Tried to unpack message with {} elements in rows into " + "Vector with {} rows", + m->rows_size(), Size)); + } + frc::Matrixd vec; + for (int i = 0; i < Size; i++) { + vec(i) = m->rows(i); + } + return vec; + } + static void Pack( google::protobuf::Message* msg, - const frc::Matrixd& value); + const frc::Matrixd& value) { + auto m = static_cast(msg); + m->clear_rows(); + for (int i = 0; i < Size; i++) { + m->add_rows(value(i)); + } + } }; - -#include "frc/proto/VectorProto.inc" diff --git a/wpimath/src/main/native/include/frc/proto/VectorProto.inc b/wpimath/src/main/native/include/frc/proto/VectorProto.inc deleted file mode 100644 index f07d7dfa77d..00000000000 --- a/wpimath/src/main/native/include/frc/proto/VectorProto.inc +++ /dev/null @@ -1,49 +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 - -#include -#include - -#include "frc/proto/VectorProto.h" -#include "wpimath.pb.h" - -template -google::protobuf::Message* -wpi::Protobuf>::New( - google::protobuf::Arena* arena) { - return wpi::CreateMessage(arena); -} - -template -frc::Matrixd -wpi::Protobuf>::Unpack( - const google::protobuf::Message& msg) { - auto m = static_cast(&msg); - if (m->rows_size() != Size) { - throw std::invalid_argument( - fmt::format("Tried to unpack message with {} elements in rows into " - "Vector with {} rows", - m->rows_size(), Size)); - } - frc::Matrixd vec; - for (int i = 0; i < Size; i++) { - vec(i) = m->rows(i); - } - return vec; -} - -template -void wpi::Protobuf>::Pack( - google::protobuf::Message* msg, - const frc::Matrixd& value) { - auto m = static_cast(msg); - m->clear_rows(); - for (int i = 0; i < Size; i++) { - m->add_rows(value(i)); - } -} diff --git a/wpimath/src/main/native/include/frc/struct/MatrixStruct.h b/wpimath/src/main/native/include/frc/struct/MatrixStruct.h index 926109c852e..59bc4b57121 100644 --- a/wpimath/src/main/native/include/frc/struct/MatrixStruct.h +++ b/wpimath/src/main/native/include/frc/struct/MatrixStruct.h @@ -24,13 +24,28 @@ struct wpi::Struct> { static constexpr std::string_view GetSchema() { return kSchema; } static frc::Matrixd Unpack( - std::span data); + std::span data) { + constexpr size_t kDataOff = 0; + wpi::array mat_data = + wpi::UnpackStructArray(data); + frc::Matrixd mat; + for (int i = 0; i < Rows * Cols; i++) { + mat(i) = mat_data[i]; + } + return mat; + } + static void Pack( std::span data, - const frc::Matrixd& value); + const frc::Matrixd& value) { + constexpr size_t kDataOff = 0; + wpi::array mat_data(wpi::empty_array); + for (int i = 0; i < Rows * Cols; i++) { + mat_data[i] = value(i); + } + wpi::PackStructArray(data, mat_data); + } }; static_assert(wpi::StructSerializable>); static_assert(wpi::StructSerializable>); - -#include "frc/struct/MatrixStruct.inc" diff --git a/wpimath/src/main/native/include/frc/struct/MatrixStruct.inc b/wpimath/src/main/native/include/frc/struct/MatrixStruct.inc deleted file mode 100644 index 4efda8a41de..00000000000 --- a/wpimath/src/main/native/include/frc/struct/MatrixStruct.inc +++ /dev/null @@ -1,35 +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 "frc/struct/MatrixStruct.h" - -template - requires(Cols != 1) -frc::Matrixd -wpi::Struct>::Unpack( - std::span data) { - constexpr size_t kDataOff = 0; - wpi::array mat_data = - wpi::UnpackStructArray(data); - frc::Matrixd mat; - for (int i = 0; i < Rows * Cols; i++) { - mat(i) = mat_data[i]; - } - return mat; -} - -template - requires(Cols != 1) -void wpi::Struct>::Pack( - std::span data, - const frc::Matrixd& value) { - constexpr size_t kDataOff = 0; - wpi::array mat_data(wpi::empty_array); - for (int i = 0; i < Rows * Cols; i++) { - mat_data[i] = value(i); - } - wpi::PackStructArray(data, mat_data); -} diff --git a/wpimath/src/main/native/include/frc/struct/VectorStruct.h b/wpimath/src/main/native/include/frc/struct/VectorStruct.h index d10d48ebe52..ec480240c34 100644 --- a/wpimath/src/main/native/include/frc/struct/VectorStruct.h +++ b/wpimath/src/main/native/include/frc/struct/VectorStruct.h @@ -21,13 +21,28 @@ struct wpi::Struct> { static constexpr std::string_view GetSchema() { return kSchema; } static frc::Matrixd Unpack( - std::span data); + std::span data) { + constexpr size_t kDataOff = 0; + wpi::array vec_data = + wpi::UnpackStructArray(data); + frc::Matrixd vec; + for (int i = 0; i < Size; i++) { + vec(i) = vec_data[i]; + } + return vec; + } + static void Pack( std::span data, - const frc::Matrixd& value); + const frc::Matrixd& value) { + constexpr size_t kDataOff = 0; + wpi::array vec_data(wpi::empty_array); + for (int i = 0; i < Size; i++) { + vec_data[i] = value(i); + } + wpi::PackStructArray(data, vec_data); + } }; static_assert(wpi::StructSerializable>); static_assert(wpi::StructSerializable>); - -#include "frc/struct/VectorStruct.inc" diff --git a/wpimath/src/main/native/include/frc/struct/VectorStruct.inc b/wpimath/src/main/native/include/frc/struct/VectorStruct.inc deleted file mode 100644 index 4fcfbb009dd..00000000000 --- a/wpimath/src/main/native/include/frc/struct/VectorStruct.inc +++ /dev/null @@ -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 "frc/struct/VectorStruct.h" - -template -frc::Matrixd -wpi::Struct>::Unpack( - std::span data) { - constexpr size_t kDataOff = 0; - wpi::array vec_data = - wpi::UnpackStructArray(data); - frc::Matrixd vec; - for (int i = 0; i < Size; i++) { - vec(i) = vec_data[i]; - } - return vec; -} - -template -void wpi::Struct>::Pack( - std::span data, - const frc::Matrixd& value) { - constexpr size_t kDataOff = 0; - wpi::array vec_data(wpi::empty_array); - for (int i = 0; i < Size; i++) { - vec_data[i] = value(i); - } - wpi::PackStructArray(data, vec_data); -} diff --git a/wpimath/src/main/native/include/frc/system/proto/LinearSystemProto.h b/wpimath/src/main/native/include/frc/system/proto/LinearSystemProto.h index f47f63e67c0..36eea0802e8 100644 --- a/wpimath/src/main/native/include/frc/system/proto/LinearSystemProto.h +++ b/wpimath/src/main/native/include/frc/system/proto/LinearSystemProto.h @@ -4,17 +4,49 @@ #pragma once +#include + +#include +#include #include +#include "frc/proto/MatrixProto.h" #include "frc/system/LinearSystem.h" +#include "system.pb.h" template struct wpi::Protobuf> { - static google::protobuf::Message* New(google::protobuf::Arena* arena); + static google::protobuf::Message* New(google::protobuf::Arena* arena) { + return wpi::CreateMessage(arena); + } + static frc::LinearSystem Unpack( - const google::protobuf::Message& msg); + const google::protobuf::Message& msg) { + auto m = static_cast(&msg); + if (m->num_states() != States || m->num_inputs() != Inputs || + m->num_outputs() != Outputs) { + throw std::invalid_argument(fmt::format( + "Tried to unpack message with {} states and {} inputs and {} outputs " + "into LinearSystem with {} states and {} inputs and {} outputs", + m->num_states(), m->num_inputs(), m->num_outputs(), States, Inputs, + Outputs)); + } + return frc::LinearSystem{ + wpi::UnpackProtobuf>(m->wpi_a()), + wpi::UnpackProtobuf>(m->wpi_b()), + wpi::UnpackProtobuf>(m->wpi_c()), + wpi::UnpackProtobuf>(m->wpi_d())}; + } + static void Pack(google::protobuf::Message* msg, - const frc::LinearSystem& value); + const frc::LinearSystem& value) { + auto m = static_cast(msg); + m->set_num_states(States); + m->set_num_inputs(Inputs); + m->set_num_outputs(Outputs); + wpi::PackProtobuf(m->mutable_a(), value.A()); + wpi::PackProtobuf(m->mutable_b(), value.B()); + wpi::PackProtobuf(m->mutable_c(), value.C()); + wpi::PackProtobuf(m->mutable_d(), value.D()); + } }; - -#include "frc/system/proto/LinearSystemProto.inc" diff --git a/wpimath/src/main/native/include/frc/system/proto/LinearSystemProto.inc b/wpimath/src/main/native/include/frc/system/proto/LinearSystemProto.inc deleted file mode 100644 index 5151f4e17b8..00000000000 --- a/wpimath/src/main/native/include/frc/system/proto/LinearSystemProto.inc +++ /dev/null @@ -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. - -#pragma once - -#include - -#include -#include - -#include "frc/proto/MatrixProto.h" -#include "frc/system/proto/LinearSystemProto.h" -#include "system.pb.h" - -template -google::protobuf::Message* -wpi::Protobuf>::New( - google::protobuf::Arena* arena) { - return wpi::CreateMessage(arena); -} - -template -frc::LinearSystem -wpi::Protobuf>::Unpack( - const google::protobuf::Message& msg) { - auto m = static_cast(&msg); - if (m->num_states() != States || m->num_inputs() != Inputs || - m->num_outputs() != Outputs) { - throw std::invalid_argument(fmt::format( - "Tried to unpack message with {} states and {} inputs and {} outputs " - "into LinearSystem with {} states and {} inputs and {} outputs", - m->num_states(), m->num_inputs(), m->num_outputs(), States, Inputs, - Outputs)); - } - return frc::LinearSystem{ - wpi::UnpackProtobuf>(m->wpi_a()), - wpi::UnpackProtobuf>(m->wpi_b()), - wpi::UnpackProtobuf>(m->wpi_c()), - wpi::UnpackProtobuf>(m->wpi_d())}; -} - -template -void wpi::Protobuf>::Pack( - google::protobuf::Message* msg, - const frc::LinearSystem& value) { - auto m = static_cast(msg); - m->set_num_states(States); - m->set_num_inputs(Inputs); - m->set_num_outputs(Outputs); - wpi::PackProtobuf(m->mutable_a(), value.A()); - wpi::PackProtobuf(m->mutable_b(), value.B()); - wpi::PackProtobuf(m->mutable_c(), value.C()); - wpi::PackProtobuf(m->mutable_d(), value.D()); -} diff --git a/wpimath/src/main/native/include/frc/system/struct/LinearSystemStruct.h b/wpimath/src/main/native/include/frc/system/struct/LinearSystemStruct.h index e8731a966bc..74a76bce0b6 100644 --- a/wpimath/src/main/native/include/frc/system/struct/LinearSystemStruct.h +++ b/wpimath/src/main/native/include/frc/system/struct/LinearSystemStruct.h @@ -32,9 +32,36 @@ struct wpi::Struct> { static constexpr std::string_view GetSchema() { return kSchema; } static frc::LinearSystem Unpack( - std::span data); + std::span data) { + constexpr size_t kAOff = 0; + constexpr size_t kBOff = + kAOff + wpi::GetStructSize>(); + constexpr size_t kCOff = + kBOff + wpi::GetStructSize>(); + constexpr size_t kDOff = + kCOff + wpi::GetStructSize>(); + return frc::LinearSystem{ + wpi::UnpackStruct, kAOff>(data), + wpi::UnpackStruct, kBOff>(data), + wpi::UnpackStruct, kCOff>(data), + wpi::UnpackStruct, kDOff>(data)}; + } + static void Pack(std::span data, - const frc::LinearSystem& value); + const frc::LinearSystem& value) { + constexpr size_t kAOff = 0; + constexpr size_t kBOff = + kAOff + wpi::GetStructSize>(); + constexpr size_t kCOff = + kBOff + wpi::GetStructSize>(); + constexpr size_t kDOff = + kCOff + wpi::GetStructSize>(); + wpi::PackStruct(data, value.A()); + wpi::PackStruct(data, value.B()); + wpi::PackStruct(data, value.C()); + wpi::PackStruct(data, value.D()); + } + static void ForEachNested( std::invocable auto fn) { wpi::ForEachStructSchema>(fn); @@ -48,5 +75,3 @@ static_assert(wpi::StructSerializable>); static_assert(wpi::HasNestedStruct>); static_assert(wpi::StructSerializable>); static_assert(wpi::HasNestedStruct>); - -#include "frc/system/struct/LinearSystemStruct.inc" diff --git a/wpimath/src/main/native/include/frc/system/struct/LinearSystemStruct.inc b/wpimath/src/main/native/include/frc/system/struct/LinearSystemStruct.inc deleted file mode 100644 index fbac4b97bcd..00000000000 --- a/wpimath/src/main/native/include/frc/system/struct/LinearSystemStruct.inc +++ /dev/null @@ -1,42 +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 "frc/system/struct/LinearSystemStruct.h" - -template -frc::LinearSystem -wpi::Struct>::Unpack( - std::span data) { - constexpr size_t kAOff = 0; - constexpr size_t kBOff = - kAOff + wpi::GetStructSize>(); - constexpr size_t kCOff = - kBOff + wpi::GetStructSize>(); - constexpr size_t kDOff = - kCOff + wpi::GetStructSize>(); - return frc::LinearSystem{ - wpi::UnpackStruct, kAOff>(data), - wpi::UnpackStruct, kBOff>(data), - wpi::UnpackStruct, kCOff>(data), - wpi::UnpackStruct, kDOff>(data)}; -} - -template -void wpi::Struct>::Pack( - std::span data, - const frc::LinearSystem& value) { - constexpr size_t kAOff = 0; - constexpr size_t kBOff = - kAOff + wpi::GetStructSize>(); - constexpr size_t kCOff = - kBOff + wpi::GetStructSize>(); - constexpr size_t kDOff = - kCOff + wpi::GetStructSize>(); - wpi::PackStruct(data, value.A()); - wpi::PackStruct(data, value.B()); - wpi::PackStruct(data, value.C()); - wpi::PackStruct(data, value.D()); -} diff --git a/wpimath/src/main/native/include/frc/trajectory/ExponentialProfile.h b/wpimath/src/main/native/include/frc/trajectory/ExponentialProfile.h index b5e8952b689..49ebc649ca9 100644 --- a/wpimath/src/main/native/include/frc/trajectory/ExponentialProfile.h +++ b/wpimath/src/main/native/include/frc/trajectory/ExponentialProfile.h @@ -4,8 +4,8 @@ #pragma once +#include "units/math.h" #include "units/time.h" -#include "wpimath/MathShared.h" namespace frc { @@ -134,7 +134,8 @@ class ExponentialProfile { * * @param constraints The constraints on the profile, like maximum input. */ - explicit ExponentialProfile(Constraints constraints); + explicit ExponentialProfile(Constraints constraints) + : m_constraints(constraints) {} ExponentialProfile(const ExponentialProfile&) = default; ExponentialProfile& operator=(const ExponentialProfile&) = default; @@ -152,7 +153,25 @@ class ExponentialProfile { * @return The position and velocity of the profile at time t. */ State Calculate(const units::second_t& t, const State& current, - const State& goal) const; + const State& goal) const { + auto direction = ShouldFlipInput(current, goal) ? -1 : 1; + auto u = direction * m_constraints.maxInput; + + auto inflectionPoint = CalculateInflectionPoint(current, goal, u); + auto timing = CalculateProfileTiming(current, inflectionPoint, goal, u); + + if (t < 0_s) { + return current; + } else if (t < timing.inflectionTime) { + return {ComputeDistanceFromTime(t, u, current), + ComputeVelocityFromTime(t, u, current)}; + } else if (t < timing.totalTime) { + return {ComputeDistanceFromTime(t - timing.totalTime, -u, goal), + ComputeVelocityFromTime(t - timing.totalTime, -u, goal)}; + } else { + return goal; + } + } /** * Calculates the point after which the fastest way to reach the goal state is @@ -162,7 +181,13 @@ class ExponentialProfile { * @param goal The desired state when the profile is complete. * @return The position and velocity of the profile at the inflection point. */ - State CalculateInflectionPoint(const State& current, const State& goal) const; + State CalculateInflectionPoint(const State& current, + const State& goal) const { + auto direction = ShouldFlipInput(current, goal) ? -1 : 1; + auto u = direction * m_constraints.maxInput; + + return CalculateInflectionPoint(current, goal, u); + } /** * Calculates the time it will take for this profile to reach the goal state. @@ -171,7 +196,11 @@ class ExponentialProfile { * @param goal The desired state when the profile is complete. * @return The total duration of this profile. */ - units::second_t TimeLeftUntil(const State& current, const State& goal) const; + units::second_t TimeLeftUntil(const State& current, const State& goal) const { + auto timing = CalculateProfileTiming(current, goal); + + return timing.totalTime; + } /** * Calculates the time it will take for this profile to reach the inflection @@ -182,7 +211,13 @@ class ExponentialProfile { * @return The timing information for this profile. */ ProfileTiming CalculateProfileTiming(const State& current, - const State& goal) const; + const State& goal) const { + auto direction = ShouldFlipInput(current, goal) ? -1 : 1; + auto u = direction * m_constraints.maxInput; + + auto inflectionPoint = CalculateInflectionPoint(current, goal, u); + return CalculateProfileTiming(current, inflectionPoint, goal, u); + } private: /** @@ -196,7 +231,19 @@ class ExponentialProfile { * @return The position and velocity of the profile at the inflection point. */ State CalculateInflectionPoint(const State& current, const State& goal, - const Input_t& input) const; + const Input_t& input) const { + auto u = input; + + if (current == goal) { + return current; + } + + auto inflectionVelocity = SolveForInflectionVelocity(u, current, goal); + auto inflectionPosition = + ComputeDistanceFromVelocity(inflectionVelocity, -u, goal); + + return {inflectionPosition, inflectionVelocity}; + } /** * Calculates the time it will take for this profile to reach the inflection @@ -212,7 +259,59 @@ class ExponentialProfile { ProfileTiming CalculateProfileTiming(const State& current, const State& inflectionPoint, const State& goal, - const Input_t& input) const; + const Input_t& input) const { + auto u = input; + auto u_dir = units::math::abs(u) / u; + + units::second_t inflectionT_forward; + + // We need to handle 5 cases here: + // + // - Approaching -maxVelocity from below + // - Approaching -maxVelocity from above + // - Approaching maxVelocity from below + // - Approaching maxVelocity from above + // - At +-maxVelocity + // + // For cases 1 and 3, we want to subtract epsilon from the inflection point + // velocity For cases 2 and 4, we want to add epsilon to the inflection + // point velocity. For case 5, we have reached inflection point velocity. + auto epsilon = Velocity_t(1e-9); + if (units::math::abs(u_dir * m_constraints.MaxVelocity() - + inflectionPoint.velocity) < epsilon) { + auto solvableV = inflectionPoint.velocity; + units::second_t t_to_solvable_v; + Distance_t x_at_solvable_v; + if (units::math::abs(current.velocity - inflectionPoint.velocity) < + epsilon) { + t_to_solvable_v = 0_s; + x_at_solvable_v = current.position; + } else { + if (units::math::abs(current.velocity) > m_constraints.MaxVelocity()) { + solvableV += u_dir * epsilon; + } else { + solvableV -= u_dir * epsilon; + } + + t_to_solvable_v = + ComputeTimeFromVelocity(solvableV, u, current.velocity); + x_at_solvable_v = ComputeDistanceFromVelocity(solvableV, u, current); + } + + inflectionT_forward = + t_to_solvable_v + u_dir * + (inflectionPoint.position - x_at_solvable_v) / + m_constraints.MaxVelocity(); + } else { + inflectionT_forward = ComputeTimeFromVelocity(inflectionPoint.velocity, u, + current.velocity); + } + + auto inflectionT_backward = + ComputeTimeFromVelocity(inflectionPoint.velocity, -u, goal.velocity); + + return {inflectionT_forward, inflectionT_forward - inflectionT_backward}; + } /** * Calculates the position reached after t seconds when applying an input from @@ -226,7 +325,16 @@ class ExponentialProfile { */ Distance_t ComputeDistanceFromTime(const units::second_t& time, const Input_t& input, - const State& initial) const; + const State& initial) const { + auto A = m_constraints.A; + auto B = m_constraints.B; + auto u = input; + + return initial.position + + (-B * u * time + + (initial.velocity + B * u / A) * (units::math::exp(A * time) - 1)) / + A; + } /** * Calculates the velocity reached after t seconds when applying an input from @@ -240,7 +348,14 @@ class ExponentialProfile { */ Velocity_t ComputeVelocityFromTime(const units::second_t& time, const Input_t& input, - const State& initial) const; + const State& initial) const { + auto A = m_constraints.A; + auto B = m_constraints.B; + auto u = input; + + return (initial.velocity + B * u / A) * units::math::exp(A * time) - + B * u / A; + } /** * Calculates the time required to reach a specified velocity given the @@ -254,7 +369,13 @@ class ExponentialProfile { */ units::second_t ComputeTimeFromVelocity(const Velocity_t& velocity, const Input_t& input, - const Velocity_t& initial) const; + const Velocity_t& initial) const { + auto A = m_constraints.A; + auto B = m_constraints.B; + auto u = input; + + return units::math::log((A * velocity + B * u) / (A * initial + B * u)) / A; + } /** * Calculates the distance reached at the same time as the given velocity when @@ -268,7 +389,16 @@ class ExponentialProfile { */ Distance_t ComputeDistanceFromVelocity(const Velocity_t& velocity, const Input_t& input, - const State& initial) const; + const State& initial) const { + auto A = m_constraints.A; + auto B = m_constraints.B; + auto u = input; + + return initial.position + (velocity - initial.velocity) / A - + B * u / (A * A) * + units::math::log((A * velocity + B * u) / + (A * initial.velocity + B * u)); + } /** * Calculates the velocity at which input should be reversed in order to reach @@ -282,7 +412,30 @@ class ExponentialProfile { */ Velocity_t SolveForInflectionVelocity(const Input_t& input, const State& current, - const State& goal) const; + const State& goal) const { + auto A = m_constraints.A; + auto B = m_constraints.B; + auto u = input; + + auto u_dir = u / units::math::abs(u); + + auto position_delta = goal.position - current.position; + auto velocity_delta = goal.velocity - current.velocity; + + auto scalar = (A * current.velocity + B * u) * (A * goal.velocity - B * u); + auto power = -A / B / u * (A * position_delta - velocity_delta); + + auto a = -A * A; + auto c = B * B * u * u + scalar * units::math::exp(power); + + if (-1e-9 < c.value() && c.value() < 0) { + // numeric instability - the heuristic gets it right but c is around + // -1e-13 + return Velocity_t(0); + } + + return u_dir * units::math::sqrt(-c / a); + } /** * Returns true if the profile should be inverted. @@ -293,10 +446,33 @@ class ExponentialProfile { * @param current The initial state (usually the current state). * @param goal The desired state when the profile is complete. */ - bool ShouldFlipInput(const State& current, const State& goal) const; + bool ShouldFlipInput(const State& current, const State& goal) const { + auto u = m_constraints.maxInput; + + auto v0 = current.velocity; + auto xf = goal.position; + auto vf = goal.velocity; + + auto x_forward = ComputeDistanceFromVelocity(vf, u, current); + auto x_reverse = ComputeDistanceFromVelocity(vf, -u, current); + + if (v0 >= m_constraints.MaxVelocity()) { + return xf < x_reverse; + } + + if (v0 <= -m_constraints.MaxVelocity()) { + return xf < x_forward; + } + + auto a = v0 >= Velocity_t(0); + auto b = vf >= Velocity_t(0); + auto c = xf >= x_forward; + auto d = xf >= x_reverse; + + return (a && !d) || (b && !c) || (!c && !d); + } Constraints m_constraints; }; -} // namespace frc -#include "ExponentialProfile.inc" +} // namespace frc diff --git a/wpimath/src/main/native/include/frc/trajectory/ExponentialProfile.inc b/wpimath/src/main/native/include/frc/trajectory/ExponentialProfile.inc deleted file mode 100644 index 82e33313f7a..00000000000 --- a/wpimath/src/main/native/include/frc/trajectory/ExponentialProfile.inc +++ /dev/null @@ -1,251 +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 - -#include "frc/trajectory/ExponentialProfile.h" -#include "units/math.h" - -namespace frc { -template -ExponentialProfile::ExponentialProfile(Constraints constraints) - : m_constraints(constraints) {} - -template -typename ExponentialProfile::State -ExponentialProfile::Calculate(const units::second_t& t, - const State& current, - const State& goal) const { - auto direction = ShouldFlipInput(current, goal) ? -1 : 1; - auto u = direction * m_constraints.maxInput; - - auto inflectionPoint = CalculateInflectionPoint(current, goal, u); - auto timing = CalculateProfileTiming(current, inflectionPoint, goal, u); - - if (t < 0_s) { - return current; - } else if (t < timing.inflectionTime) { - return {ComputeDistanceFromTime(t, u, current), - ComputeVelocityFromTime(t, u, current)}; - } else if (t < timing.totalTime) { - return {ComputeDistanceFromTime(t - timing.totalTime, -u, goal), - ComputeVelocityFromTime(t - timing.totalTime, -u, goal)}; - } else { - return goal; - } -} - -template -typename ExponentialProfile::State -ExponentialProfile::CalculateInflectionPoint( - const State& current, const State& goal) const { - auto direction = ShouldFlipInput(current, goal) ? -1 : 1; - auto u = direction * m_constraints.maxInput; - - return CalculateInflectionPoint(current, goal, u); -} - -template -units::second_t ExponentialProfile::TimeLeftUntil( - const State& current, const State& goal) const { - auto timing = CalculateProfileTiming(current, goal); - - return timing.totalTime; -} - -template -typename ExponentialProfile::ProfileTiming -ExponentialProfile::CalculateProfileTiming( - const State& current, const State& goal) const { - auto direction = ShouldFlipInput(current, goal) ? -1 : 1; - auto u = direction * m_constraints.maxInput; - - auto inflectionPoint = CalculateInflectionPoint(current, goal, u); - return CalculateProfileTiming(current, inflectionPoint, goal, u); -} - -template -typename ExponentialProfile::State -ExponentialProfile::CalculateInflectionPoint( - const State& current, const State& goal, const Input_t& input) const { - auto u = input; - - if (current == goal) { - return current; - } - - auto inflectionVelocity = SolveForInflectionVelocity(u, current, goal); - auto inflectionPosition = - ComputeDistanceFromVelocity(inflectionVelocity, -u, goal); - - return {inflectionPosition, inflectionVelocity}; -} - -template -typename ExponentialProfile::ProfileTiming -ExponentialProfile::CalculateProfileTiming( - const State& current, const State& inflectionPoint, const State& goal, - const Input_t& input) const { - auto u = input; - auto u_dir = units::math::abs(u) / u; - - units::second_t inflectionT_forward; - - // We need to handle 5 cases here: - // - // - Approaching -maxVelocity from below - // - Approaching -maxVelocity from above - // - Approaching maxVelocity from below - // - Approaching maxVelocity from above - // - At +-maxVelocity - // - // For cases 1 and 3, we want to subtract epsilon from the inflection point - // velocity For cases 2 and 4, we want to add epsilon to the inflection point - // velocity. For case 5, we have reached inflection point velocity. - auto epsilon = Velocity_t(1e-9); - if (units::math::abs(u_dir * m_constraints.MaxVelocity() - - inflectionPoint.velocity) < epsilon) { - auto solvableV = inflectionPoint.velocity; - units::second_t t_to_solvable_v; - Distance_t x_at_solvable_v; - if (units::math::abs(current.velocity - inflectionPoint.velocity) < - epsilon) { - t_to_solvable_v = 0_s; - x_at_solvable_v = current.position; - } else { - if (units::math::abs(current.velocity) > m_constraints.MaxVelocity()) { - solvableV += u_dir * epsilon; - } else { - solvableV -= u_dir * epsilon; - } - - t_to_solvable_v = ComputeTimeFromVelocity(solvableV, u, current.velocity); - x_at_solvable_v = ComputeDistanceFromVelocity(solvableV, u, current); - } - - inflectionT_forward = - t_to_solvable_v + u_dir * (inflectionPoint.position - x_at_solvable_v) / - m_constraints.MaxVelocity(); - } else { - inflectionT_forward = - ComputeTimeFromVelocity(inflectionPoint.velocity, u, current.velocity); - } - - auto inflectionT_backward = - ComputeTimeFromVelocity(inflectionPoint.velocity, -u, goal.velocity); - - return {inflectionT_forward, inflectionT_forward - inflectionT_backward}; -} - -template -typename ExponentialProfile::Distance_t -ExponentialProfile::ComputeDistanceFromTime( - const units::second_t& time, const Input_t& input, - const State& initial) const { - auto A = m_constraints.A; - auto B = m_constraints.B; - auto u = input; - - return initial.position + - (-B * u * time + - (initial.velocity + B * u / A) * (units::math::exp(A * time) - 1)) / - A; -} - -template -typename ExponentialProfile::Velocity_t -ExponentialProfile::ComputeVelocityFromTime( - const units::second_t& time, const Input_t& input, - const State& initial) const { - auto A = m_constraints.A; - auto B = m_constraints.B; - auto u = input; - - return (initial.velocity + B * u / A) * units::math::exp(A * time) - - B * u / A; -} - -template -units::second_t ExponentialProfile::ComputeTimeFromVelocity( - const Velocity_t& velocity, const Input_t& input, - const Velocity_t& initial) const { - auto A = m_constraints.A; - auto B = m_constraints.B; - auto u = input; - - return units::math::log((A * velocity + B * u) / (A * initial + B * u)) / A; -} - -template -typename ExponentialProfile::Distance_t -ExponentialProfile::ComputeDistanceFromVelocity( - const Velocity_t& velocity, const Input_t& input, - const State& initial) const { - auto A = m_constraints.A; - auto B = m_constraints.B; - auto u = input; - - return initial.position + (velocity - initial.velocity) / A - - B * u / (A * A) * - units::math::log((A * velocity + B * u) / - (A * initial.velocity + B * u)); -} - -template -typename ExponentialProfile::Velocity_t -ExponentialProfile::SolveForInflectionVelocity( - const Input_t& input, const State& current, const State& goal) const { - auto A = m_constraints.A; - auto B = m_constraints.B; - auto u = input; - - auto u_dir = u / units::math::abs(u); - - auto position_delta = goal.position - current.position; - auto velocity_delta = goal.velocity - current.velocity; - - auto scalar = (A * current.velocity + B * u) * (A * goal.velocity - B * u); - auto power = -A / B / u * (A * position_delta - velocity_delta); - - auto a = -A * A; - auto c = B * B * u * u + scalar * units::math::exp(power); - - if (-1e-9 < c.value() && c.value() < 0) { - // numeric instability - the heuristic gets it right but c is around -1e-13 - return Velocity_t(0); - } - - return u_dir * units::math::sqrt(-c / a); -} - -template -bool ExponentialProfile::ShouldFlipInput( - const State& current, const State& goal) const { - auto u = m_constraints.maxInput; - - auto v0 = current.velocity; - auto xf = goal.position; - auto vf = goal.velocity; - - auto x_forward = ComputeDistanceFromVelocity(vf, u, current); - auto x_reverse = ComputeDistanceFromVelocity(vf, -u, current); - - if (v0 >= m_constraints.MaxVelocity()) { - return xf < x_reverse; - } - - if (v0 <= -m_constraints.MaxVelocity()) { - return xf < x_forward; - } - - auto a = v0 >= Velocity_t(0); - auto b = vf >= Velocity_t(0); - auto c = xf >= x_forward; - auto d = xf >= x_reverse; - - return (a && !d) || (b && !c) || (!c && !d); -} -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/trajectory/TrapezoidProfile.h b/wpimath/src/main/native/include/frc/trajectory/TrapezoidProfile.h index 08df10c8d94..20a88176a87 100644 --- a/wpimath/src/main/native/include/frc/trajectory/TrapezoidProfile.h +++ b/wpimath/src/main/native/include/frc/trajectory/TrapezoidProfile.h @@ -4,6 +4,7 @@ #pragma once +#include "units/math.h" #include "units/time.h" #include "wpimath/MathShared.h" @@ -101,7 +102,9 @@ class TrapezoidProfile { * * @param constraints The constraints on the profile, like maximum velocity. */ - TrapezoidProfile(Constraints constraints); // NOLINT + TrapezoidProfile(Constraints constraints) // NOLINT + : m_constraints(constraints) {} + TrapezoidProfile(const TrapezoidProfile&) = default; TrapezoidProfile& operator=(const TrapezoidProfile&) = default; TrapezoidProfile(TrapezoidProfile&&) = default; @@ -117,7 +120,74 @@ class TrapezoidProfile { * @param goal The desired state when the profile is complete. * @return The position and velocity of the profile at time t. */ - State Calculate(units::second_t t, State current, State goal); + State Calculate(units::second_t t, State current, State goal) { + m_direction = ShouldFlipAcceleration(current, goal) ? -1 : 1; + m_current = Direct(current); + goal = Direct(goal); + if (m_current.velocity > m_constraints.maxVelocity) { + m_current.velocity = m_constraints.maxVelocity; + } + + // Deal with a possibly truncated motion profile (with nonzero initial or + // final velocity) by calculating the parameters as if the profile began and + // ended at zero velocity + units::second_t cutoffBegin = + m_current.velocity / m_constraints.maxAcceleration; + Distance_t cutoffDistBegin = + cutoffBegin * cutoffBegin * m_constraints.maxAcceleration / 2.0; + + units::second_t cutoffEnd = goal.velocity / m_constraints.maxAcceleration; + Distance_t cutoffDistEnd = + cutoffEnd * cutoffEnd * m_constraints.maxAcceleration / 2.0; + + // Now we can calculate the parameters as if it was a full trapezoid instead + // of a truncated one + + Distance_t fullTrapezoidDist = + cutoffDistBegin + (goal.position - m_current.position) + cutoffDistEnd; + units::second_t accelerationTime = + m_constraints.maxVelocity / m_constraints.maxAcceleration; + + Distance_t fullSpeedDist = + fullTrapezoidDist - + accelerationTime * accelerationTime * m_constraints.maxAcceleration; + + // Handle the case where the profile never reaches full speed + if (fullSpeedDist < Distance_t{0}) { + accelerationTime = + units::math::sqrt(fullTrapezoidDist / m_constraints.maxAcceleration); + fullSpeedDist = Distance_t{0}; + } + + m_endAccel = accelerationTime - cutoffBegin; + m_endFullSpeed = m_endAccel + fullSpeedDist / m_constraints.maxVelocity; + m_endDecel = m_endFullSpeed + accelerationTime - cutoffEnd; + State result = m_current; + + if (t < m_endAccel) { + result.velocity += t * m_constraints.maxAcceleration; + result.position += + (m_current.velocity + t * m_constraints.maxAcceleration / 2.0) * t; + } else if (t < m_endFullSpeed) { + result.velocity = m_constraints.maxVelocity; + result.position += (m_current.velocity + + m_endAccel * m_constraints.maxAcceleration / 2.0) * + m_endAccel + + m_constraints.maxVelocity * (t - m_endAccel); + } else if (t <= m_endDecel) { + result.velocity = + goal.velocity + (m_endDecel - t) * m_constraints.maxAcceleration; + units::second_t timeLeft = m_endDecel - t; + result.position = + goal.position - + (goal.velocity + timeLeft * m_constraints.maxAcceleration / 2.0) * + timeLeft; + } else { + result = goal; + } + + return Direct(result); + } /** * Returns the time left until a target distance in the profile is reached. @@ -125,7 +195,71 @@ class TrapezoidProfile { * @param target The target distance. * @return The time left until a target distance in the profile is reached. */ - units::second_t TimeLeftUntil(Distance_t target) const; + units::second_t TimeLeftUntil(Distance_t target) const { + Distance_t position = m_current.position * m_direction; + Velocity_t velocity = m_current.velocity * m_direction; + + units::second_t endAccel = m_endAccel * m_direction; + units::second_t endFullSpeed = m_endFullSpeed * m_direction - endAccel; + + if (target < position) { + endAccel *= -1.0; + endFullSpeed *= -1.0; + velocity *= -1.0; + } + + endAccel = units::math::max(endAccel, 0_s); + endFullSpeed = units::math::max(endFullSpeed, 0_s); + + const Acceleration_t acceleration = m_constraints.maxAcceleration; + const Acceleration_t deceleration = -m_constraints.maxAcceleration; + + Distance_t distToTarget = units::math::abs(target - position); + + if (distToTarget < Distance_t{1e-6}) { + return 0_s; + } + + Distance_t accelDist = + velocity * endAccel + 0.5 * acceleration * endAccel * endAccel; + + Velocity_t decelVelocity; + if (endAccel > 0_s) { + decelVelocity = units::math::sqrt( + units::math::abs(velocity * velocity + 2 * acceleration * accelDist)); + } else { + decelVelocity = velocity; + } + + Distance_t fullSpeedDist = m_constraints.maxVelocity * endFullSpeed; + Distance_t decelDist; + + if (accelDist > distToTarget) { + accelDist = distToTarget; + fullSpeedDist = Distance_t{0}; + decelDist = Distance_t{0}; + } else if (accelDist + fullSpeedDist > distToTarget) { + fullSpeedDist = distToTarget - accelDist; + decelDist = Distance_t{0}; + } else { + decelDist = distToTarget - fullSpeedDist - accelDist; + } + + units::second_t accelTime = + (-velocity + units::math::sqrt(units::math::abs( + velocity * velocity + 2 * acceleration * accelDist))) / + acceleration; + + units::second_t decelTime = + (-decelVelocity + + units::math::sqrt(units::math::abs(decelVelocity * decelVelocity + + 2 * deceleration * decelDist))) / + deceleration; + + units::second_t fullSpeedTime = fullSpeedDist / m_constraints.maxVelocity; + + return accelTime + fullSpeedTime + decelTime; + } /** * Returns the total time the profile takes to reach the goal. @@ -176,6 +310,5 @@ class TrapezoidProfile { units::second_t m_endFullSpeed; units::second_t m_endDecel; }; -} // namespace frc -#include "TrapezoidProfile.inc" +} // namespace frc diff --git a/wpimath/src/main/native/include/frc/trajectory/TrapezoidProfile.inc b/wpimath/src/main/native/include/frc/trajectory/TrapezoidProfile.inc deleted file mode 100644 index 4b1eff72b69..00000000000 --- a/wpimath/src/main/native/include/frc/trajectory/TrapezoidProfile.inc +++ /dev/null @@ -1,156 +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 - -#include "frc/trajectory/TrapezoidProfile.h" -#include "units/math.h" - -namespace frc { -template -TrapezoidProfile::TrapezoidProfile(Constraints constraints) - : m_constraints(constraints) {} - -template -typename TrapezoidProfile::State -TrapezoidProfile::Calculate(units::second_t t, State current, - State goal) { - m_direction = ShouldFlipAcceleration(current, goal) ? -1 : 1; - m_current = Direct(current); - goal = Direct(goal); - if (m_current.velocity > m_constraints.maxVelocity) { - m_current.velocity = m_constraints.maxVelocity; - } - - // Deal with a possibly truncated motion profile (with nonzero initial or - // final velocity) by calculating the parameters as if the profile began and - // ended at zero velocity - units::second_t cutoffBegin = - m_current.velocity / m_constraints.maxAcceleration; - Distance_t cutoffDistBegin = - cutoffBegin * cutoffBegin * m_constraints.maxAcceleration / 2.0; - - units::second_t cutoffEnd = goal.velocity / m_constraints.maxAcceleration; - Distance_t cutoffDistEnd = - cutoffEnd * cutoffEnd * m_constraints.maxAcceleration / 2.0; - - // Now we can calculate the parameters as if it was a full trapezoid instead - // of a truncated one - - Distance_t fullTrapezoidDist = - cutoffDistBegin + (goal.position - m_current.position) + cutoffDistEnd; - units::second_t accelerationTime = - m_constraints.maxVelocity / m_constraints.maxAcceleration; - - Distance_t fullSpeedDist = - fullTrapezoidDist - - accelerationTime * accelerationTime * m_constraints.maxAcceleration; - - // Handle the case where the profile never reaches full speed - if (fullSpeedDist < Distance_t{0}) { - accelerationTime = - units::math::sqrt(fullTrapezoidDist / m_constraints.maxAcceleration); - fullSpeedDist = Distance_t{0}; - } - - m_endAccel = accelerationTime - cutoffBegin; - m_endFullSpeed = m_endAccel + fullSpeedDist / m_constraints.maxVelocity; - m_endDecel = m_endFullSpeed + accelerationTime - cutoffEnd; - State result = m_current; - - if (t < m_endAccel) { - result.velocity += t * m_constraints.maxAcceleration; - result.position += - (m_current.velocity + t * m_constraints.maxAcceleration / 2.0) * t; - } else if (t < m_endFullSpeed) { - result.velocity = m_constraints.maxVelocity; - result.position += (m_current.velocity + - m_endAccel * m_constraints.maxAcceleration / 2.0) * - m_endAccel + - m_constraints.maxVelocity * (t - m_endAccel); - } else if (t <= m_endDecel) { - result.velocity = - goal.velocity + (m_endDecel - t) * m_constraints.maxAcceleration; - units::second_t timeLeft = m_endDecel - t; - result.position = - goal.position - - (goal.velocity + timeLeft * m_constraints.maxAcceleration / 2.0) * - timeLeft; - } else { - result = goal; - } - - return Direct(result); -} - -template -units::second_t TrapezoidProfile::TimeLeftUntil( - Distance_t target) const { - Distance_t position = m_current.position * m_direction; - Velocity_t velocity = m_current.velocity * m_direction; - - units::second_t endAccel = m_endAccel * m_direction; - units::second_t endFullSpeed = m_endFullSpeed * m_direction - endAccel; - - if (target < position) { - endAccel *= -1.0; - endFullSpeed *= -1.0; - velocity *= -1.0; - } - - endAccel = units::math::max(endAccel, 0_s); - endFullSpeed = units::math::max(endFullSpeed, 0_s); - - const Acceleration_t acceleration = m_constraints.maxAcceleration; - const Acceleration_t deceleration = -m_constraints.maxAcceleration; - - Distance_t distToTarget = units::math::abs(target - position); - - if (distToTarget < Distance_t{1e-6}) { - return 0_s; - } - - Distance_t accelDist = - velocity * endAccel + 0.5 * acceleration * endAccel * endAccel; - - Velocity_t decelVelocity; - if (endAccel > 0_s) { - decelVelocity = units::math::sqrt( - units::math::abs(velocity * velocity + 2 * acceleration * accelDist)); - } else { - decelVelocity = velocity; - } - - Distance_t fullSpeedDist = m_constraints.maxVelocity * endFullSpeed; - Distance_t decelDist; - - if (accelDist > distToTarget) { - accelDist = distToTarget; - fullSpeedDist = Distance_t{0}; - decelDist = Distance_t{0}; - } else if (accelDist + fullSpeedDist > distToTarget) { - fullSpeedDist = distToTarget - accelDist; - decelDist = Distance_t{0}; - } else { - decelDist = distToTarget - fullSpeedDist - accelDist; - } - - units::second_t accelTime = - (-velocity + units::math::sqrt(units::math::abs( - velocity * velocity + 2 * acceleration * accelDist))) / - acceleration; - - units::second_t decelTime = - (-decelVelocity + - units::math::sqrt(units::math::abs(decelVelocity * decelVelocity + - 2 * deceleration * decelDist))) / - deceleration; - - units::second_t fullSpeedTime = fullSpeedDist / m_constraints.maxVelocity; - - return accelTime + fullSpeedTime + decelTime; -} -} // namespace frc diff --git a/wpimath/src/main/native/include/frc/trajectory/constraint/SwerveDriveKinematicsConstraint.h b/wpimath/src/main/native/include/frc/trajectory/constraint/SwerveDriveKinematicsConstraint.h index d26497735d9..ac05bcfeb2f 100644 --- a/wpimath/src/main/native/include/frc/trajectory/constraint/SwerveDriveKinematicsConstraint.h +++ b/wpimath/src/main/native/include/frc/trajectory/constraint/SwerveDriveKinematicsConstraint.h @@ -8,6 +8,7 @@ #include "frc/kinematics/SwerveDriveKinematics.h" #include "frc/trajectory/constraint/TrajectoryConstraint.h" +#include "units/math.h" #include "units/velocity.h" namespace frc { @@ -22,19 +23,31 @@ class SwerveDriveKinematicsConstraint : public TrajectoryConstraint { public: SwerveDriveKinematicsConstraint( const frc::SwerveDriveKinematics& kinematics, - units::meters_per_second_t maxSpeed); + units::meters_per_second_t maxSpeed) + : m_kinematics(kinematics), m_maxSpeed(maxSpeed) {} units::meters_per_second_t MaxVelocity( const Pose2d& pose, units::curvature_t curvature, - units::meters_per_second_t velocity) const override; + units::meters_per_second_t velocity) const override { + auto xVelocity = velocity * pose.Rotation().Cos(); + auto yVelocity = velocity * pose.Rotation().Sin(); + auto wheelSpeeds = m_kinematics.ToSwerveModuleStates( + {xVelocity, yVelocity, velocity * curvature}); + m_kinematics.DesaturateWheelSpeeds(&wheelSpeeds, m_maxSpeed); + + auto normSpeeds = m_kinematics.ToChassisSpeeds(wheelSpeeds); + + return units::math::hypot(normSpeeds.vx, normSpeeds.vy); + } MinMax MinMaxAcceleration(const Pose2d& pose, units::curvature_t curvature, - units::meters_per_second_t speed) const override; + units::meters_per_second_t speed) const override { + return {}; + } private: frc::SwerveDriveKinematics m_kinematics; units::meters_per_second_t m_maxSpeed; }; -} // namespace frc -#include "SwerveDriveKinematicsConstraint.inc" +} // namespace frc diff --git a/wpimath/src/main/native/include/frc/trajectory/constraint/SwerveDriveKinematicsConstraint.inc b/wpimath/src/main/native/include/frc/trajectory/constraint/SwerveDriveKinematicsConstraint.inc deleted file mode 100644 index 5c4e5ace9d5..00000000000 --- a/wpimath/src/main/native/include/frc/trajectory/constraint/SwerveDriveKinematicsConstraint.inc +++ /dev/null @@ -1,42 +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 "frc/trajectory/constraint/SwerveDriveKinematicsConstraint.h" -#include "units/math.h" - -namespace frc { - -template -SwerveDriveKinematicsConstraint::SwerveDriveKinematicsConstraint( - const frc::SwerveDriveKinematics& kinematics, - units::meters_per_second_t maxSpeed) - : m_kinematics(kinematics), m_maxSpeed(maxSpeed) {} - -template -units::meters_per_second_t -SwerveDriveKinematicsConstraint::MaxVelocity( - const Pose2d& pose, units::curvature_t curvature, - units::meters_per_second_t velocity) const { - auto xVelocity = velocity * pose.Rotation().Cos(); - auto yVelocity = velocity * pose.Rotation().Sin(); - auto wheelSpeeds = m_kinematics.ToSwerveModuleStates( - {xVelocity, yVelocity, velocity * curvature}); - m_kinematics.DesaturateWheelSpeeds(&wheelSpeeds, m_maxSpeed); - - auto normSpeeds = m_kinematics.ToChassisSpeeds(wheelSpeeds); - - return units::math::hypot(normSpeeds.vx, normSpeeds.vy); -} - -template -TrajectoryConstraint::MinMax -SwerveDriveKinematicsConstraint::MinMaxAcceleration( - const Pose2d& pose, units::curvature_t curvature, - units::meters_per_second_t speed) const { - return {}; -} - -} // namespace frc diff --git a/wpinet/src/main/native/include/wpinet/HttpUtil.h b/wpinet/src/main/native/include/wpinet/HttpUtil.h index fcf68871a4c..0d44557f57f 100644 --- a/wpinet/src/main/native/include/wpinet/HttpUtil.h +++ b/wpinet/src/main/native/include/wpinet/HttpUtil.h @@ -316,7 +316,18 @@ class HttpRequest { } template - HttpRequest(const HttpLocation& loc, const T& extraParams); + HttpRequest(const HttpLocation& loc, const T& extraParams) + : host{loc.host}, port{loc.port} { + StringMap 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 - 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 static std::string_view GetFirst(const T& elem) { @@ -416,8 +446,10 @@ class HttpMultipartScanner { std::string m_buf; }; -} // namespace wpi +inline HttpPathRef HttpPath::drop_front(size_t n) const { + return HttpPathRef(*this, n); +} -#include "HttpUtil.inc" +} // namespace wpi #endif // WPINET_HTTPUTIL_H_ diff --git a/wpinet/src/main/native/include/wpinet/HttpUtil.inc b/wpinet/src/main/native/include/wpinet/HttpUtil.inc deleted file mode 100644 index f70b8dda01a..00000000000 --- a/wpinet/src/main/native/include/wpinet/HttpUtil.inc +++ /dev/null @@ -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 - -#include "wpinet/HttpUtil.h" - -namespace wpi { - -inline HttpPathRef HttpPath::drop_front(size_t n) const { - return HttpPathRef(*this, n); -} - -template -HttpRequest::HttpRequest(const HttpLocation& loc, const T& extraParams) - : host{loc.host}, port{loc.port} { - StringMap 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 -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_ diff --git a/wpinet/src/main/native/include/wpinet/HttpWebSocketServerConnection.h b/wpinet/src/main/native/include/wpinet/HttpWebSocketServerConnection.h index 4095a9ca460..0b273ee7301 100644 --- a/wpinet/src/main/native/include/wpinet/HttpWebSocketServerConnection.h +++ b/wpinet/src/main/native/include/wpinet/HttpWebSocketServerConnection.h @@ -37,7 +37,43 @@ class HttpWebSocketServerConnection * @param protocols Acceptable subprotocols */ HttpWebSocketServerConnection(std::shared_ptr stream, - std::span protocols); + std::span 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 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_ diff --git a/wpinet/src/main/native/include/wpinet/HttpWebSocketServerConnection.inc b/wpinet/src/main/native/include/wpinet/HttpWebSocketServerConnection.inc deleted file mode 100644 index 750439de2d9..00000000000 --- a/wpinet/src/main/native/include/wpinet/HttpWebSocketServerConnection.inc +++ /dev/null @@ -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 - -#include "wpinet/HttpWebSocketServerConnection.h" - -namespace wpi { - -template -HttpWebSocketServerConnection::HttpWebSocketServerConnection( - std::shared_ptr stream, - std::span 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 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_ diff --git a/wpiutil/src/main/native/include/wpi/circular_buffer.h b/wpiutil/src/main/native/include/wpi/circular_buffer.h index a40a627db41..44f535c21ec 100644 --- a/wpiutil/src/main/native/include/wpi/circular_buffer.h +++ b/wpiutil/src/main/native/include/wpi/circular_buffer.h @@ -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" diff --git a/wpiutil/src/main/native/include/wpi/circular_buffer.inc b/wpiutil/src/main/native/include/wpi/circular_buffer.inc deleted file mode 100644 index 038af50d821..00000000000 --- a/wpiutil/src/main/native/include/wpi/circular_buffer.inc +++ /dev/null @@ -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 -void circular_buffer::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