From e2b6beb28abef4f9ee2ee2b8b6640d8f28fb70bb Mon Sep 17 00:00:00 2001 From: Thad House Date: Thu, 23 Jan 2025 21:44:18 -0800 Subject: [PATCH 1/6] [hal, wpilib] Remove DigitalGlitchFilter (#7725) --- .../wpi/first/hal/DigitalGlitchFilterJNI.java | 65 ------ .../native/cpp/jni/DigitalGlitchFilterJNI.cpp | 79 ------- hal/src/main/native/include/hal/DIO.h | 54 ----- hal/src/main/native/sim/DIO.cpp | 28 --- hal/src/main/native/systemcore/DIO.cpp | 21 -- .../main/native/cpp/DigitalGlitchFilter.cpp | 138 ------------- .../native/include/frc/DigitalGlitchFilter.h | 138 ------------- .../main/native/include/frc/DigitalInput.h | 4 - wpilibc/src/main/native/include/frc/Encoder.h | 3 - .../first/wpilibj/DigitalGlitchFilter.java | 192 ------------------ 10 files changed, 722 deletions(-) delete mode 100644 hal/src/main/java/edu/wpi/first/hal/DigitalGlitchFilterJNI.java delete mode 100644 hal/src/main/native/cpp/jni/DigitalGlitchFilterJNI.cpp delete mode 100644 wpilibc/src/main/native/cpp/DigitalGlitchFilter.cpp delete mode 100644 wpilibc/src/main/native/include/frc/DigitalGlitchFilter.h delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalGlitchFilter.java diff --git a/hal/src/main/java/edu/wpi/first/hal/DigitalGlitchFilterJNI.java b/hal/src/main/java/edu/wpi/first/hal/DigitalGlitchFilterJNI.java deleted file mode 100644 index ececa130c55..00000000000 --- a/hal/src/main/java/edu/wpi/first/hal/DigitalGlitchFilterJNI.java +++ /dev/null @@ -1,65 +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. - -package edu.wpi.first.hal; - -/** - * Digital Glitch Filter JNI functions. - * - * @see "hal/DIO.h" - */ -public class DigitalGlitchFilterJNI extends JNIWrapper { - /** - * Writes the filter index from the FPGA. - * - *

Set the filter index used to filter out short pulses. - * - * @param digitalPortHandle the digital port handle - * @param filterIndex the filter index (Must be in the range 0 - 3, where 0 means "none" and 1 - 3 - * means filter # filterIndex - 1) - * @see "HAL_SetFilterSelect" - */ - public static native void setFilterSelect(int digitalPortHandle, int filterIndex); - - /** - * Reads the filter index from the FPGA. - * - *

Gets the filter index used to filter out short pulses. - * - * @param digitalPortHandle the digital port handle - * @return the filter index (Must be in the range 0 - 3, where 0 means "none" and 1 - 3 means - * filter # filterIndex - 1) - * @see "HAL_GetFilterSelect" - */ - public static native int getFilterSelect(int digitalPortHandle); - - /** - * Sets the filter period for the specified filter index. - * - *

Sets the filter period in FPGA cycles. Even though there are 2 different filter index - * domains (MXP vs HDR), ignore that distinction for now since it complicates the interface. That - * can be changed later. - * - * @param filterIndex the filter index, 0 - 2 - * @param fpgaCycles the number of cycles that the signal must not transition to be counted as a - * transition. - * @see "HAL_SetFilterPeriod" - */ - public static native void setFilterPeriod(int filterIndex, int fpgaCycles); - - /** - * Gets the filter period for the specified filter index. - * - *

Gets the filter period in FPGA cycles. Even though there are 2 different filter index - * domains (MXP vs HDR), ignore that distinction for now since it complicates the interface. - * - * @param filterIndex the filter index, 0 - 2 - * @return The number of FPGA cycles of the filter period. - * @see "HAL_GetFilterPeriod" - */ - public static native int getFilterPeriod(int filterIndex); - - /** Utility class. */ - private DigitalGlitchFilterJNI() {} -} diff --git a/hal/src/main/native/cpp/jni/DigitalGlitchFilterJNI.cpp b/hal/src/main/native/cpp/jni/DigitalGlitchFilterJNI.cpp deleted file mode 100644 index 762f7fbe35d..00000000000 --- a/hal/src/main/native/cpp/jni/DigitalGlitchFilterJNI.cpp +++ /dev/null @@ -1,79 +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. - -#include - -#include "HALUtil.h" -#include "edu_wpi_first_hal_DigitalGlitchFilterJNI.h" -#include "hal/DIO.h" - -using namespace hal; - -extern "C" { - -/* - * Class: edu_wpi_first_hal_DigitalGlitchFilterJNI - * Method: setFilterSelect - * Signature: (II)V - */ -JNIEXPORT void JNICALL -Java_edu_wpi_first_hal_DigitalGlitchFilterJNI_setFilterSelect - (JNIEnv* env, jclass, jint id, jint filter_index) -{ - int32_t status = 0; - - HAL_SetFilterSelect(static_cast(id), filter_index, - &status); - CheckStatus(env, status); -} - -/* - * Class: edu_wpi_first_hal_DigitalGlitchFilterJNI - * Method: getFilterSelect - * Signature: (I)I - */ -JNIEXPORT jint JNICALL -Java_edu_wpi_first_hal_DigitalGlitchFilterJNI_getFilterSelect - (JNIEnv* env, jclass, jint id) -{ - int32_t status = 0; - - jint result = - HAL_GetFilterSelect(static_cast(id), &status); - CheckStatus(env, status); - return result; -} - -/* - * Class: edu_wpi_first_hal_DigitalGlitchFilterJNI - * Method: setFilterPeriod - * Signature: (II)V - */ -JNIEXPORT void JNICALL -Java_edu_wpi_first_hal_DigitalGlitchFilterJNI_setFilterPeriod - (JNIEnv* env, jclass, jint filter_index, jint fpga_cycles) -{ - int32_t status = 0; - - HAL_SetFilterPeriod(filter_index, fpga_cycles, &status); - CheckStatus(env, status); -} - -/* - * Class: edu_wpi_first_hal_DigitalGlitchFilterJNI - * Method: getFilterPeriod - * Signature: (I)I - */ -JNIEXPORT jint JNICALL -Java_edu_wpi_first_hal_DigitalGlitchFilterJNI_getFilterPeriod - (JNIEnv* env, jclass, jint filter_index) -{ - int32_t status = 0; - - jint result = HAL_GetFilterPeriod(filter_index, &status); - CheckStatus(env, status); - return result; -} - -} // extern "C" diff --git a/hal/src/main/native/include/hal/DIO.h b/hal/src/main/native/include/hal/DIO.h index b81044cde83..f62e7451add 100644 --- a/hal/src/main/native/include/hal/DIO.h +++ b/hal/src/main/native/include/hal/DIO.h @@ -194,60 +194,6 @@ HAL_Bool HAL_IsPulsing(HAL_DigitalHandle dioPortHandle, int32_t* status); * @return true if a pulse on some line is in progress */ HAL_Bool HAL_IsAnyPulsing(int32_t* status); - -/** - * Writes the filter index from the FPGA. - * - * Set the filter index used to filter out short pulses. - * - * @param[in] dioPortHandle the digital port handle - * @param[in] filterIndex the filter index (Must be in the range 0 - 3, where - * 0 means "none" and 1 - 3 means filter # filterIndex - * - 1) - * @param[out] status Error status variable. 0 on success. - */ -void HAL_SetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t filterIndex, - int32_t* status); - -/** - * Reads the filter index from the FPGA. - * - * Gets the filter index used to filter out short pulses. - * - * @param[in] dioPortHandle the digital port handle - * @param[out] status Error status variable. 0 on success. - * @return filterIndex the filter index (Must be in the range 0 - 3, where 0 - * means "none" and 1 - 3 means filter # filterIndex - 1) - */ -int32_t HAL_GetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t* status); - -/** - * Sets the filter period for the specified filter index. - * - * Sets the filter period in FPGA cycles. Even though there are 2 different - * filter index domains (MXP vs HDR), ignore that distinction for now since it - * complicates the interface. That can be changed later. - * - * @param[in] filterIndex the filter index, 0 - 2 - * @param[in] value the number of cycles that the signal must not - * transition to be counted as a transition. - * @param[out] status Error status variable. 0 on success. - */ -void HAL_SetFilterPeriod(int32_t filterIndex, int64_t value, int32_t* status); - -/** - * Gets the filter period for the specified filter index. - * - * Gets the filter period in FPGA cycles. Even though there are 2 different - * filter index domains (MXP vs HDR), ignore that distinction for now since it - * complicates the interface. Set status to NiFpga_Status_SoftwareFault if the - * filter values mismatch. - * - * @param[in] filterIndex the filter index, 0 - 2 - * @param[out] status Error status variable. 0 on success. - * @return The number of FPGA cycles of the filter period. - */ -int64_t HAL_GetFilterPeriod(int32_t filterIndex, int32_t* status); #ifdef __cplusplus } // extern "C" #endif diff --git a/hal/src/main/native/sim/DIO.cpp b/hal/src/main/native/sim/DIO.cpp index 1148b75d608..7f87f80fad8 100644 --- a/hal/src/main/native/sim/DIO.cpp +++ b/hal/src/main/native/sim/DIO.cpp @@ -269,32 +269,4 @@ HAL_Bool HAL_IsPulsing(HAL_DigitalHandle dioPortHandle, int32_t* status) { HAL_Bool HAL_IsAnyPulsing(int32_t* status) { return false; // TODO(Thad) Figure this out } - -void HAL_SetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t filterIndex, - int32_t* status) { - auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO); - if (port == nullptr) { - *status = HAL_HANDLE_ERROR; - return; - } - // mimics athena HAL - port->filterIndex = filterIndex % 4; -} - -int32_t HAL_GetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t* status) { - auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO); - if (port == nullptr) { - *status = HAL_HANDLE_ERROR; - return 0; - } - return port->filterIndex; -} - -void HAL_SetFilterPeriod(int32_t filterIndex, int64_t value, int32_t* status) { - // TODO(Thad) figure this out -} - -int64_t HAL_GetFilterPeriod(int32_t filterIndex, int32_t* status) { - return 0; // TODO(Thad) figure this out -} } // extern "C" diff --git a/hal/src/main/native/systemcore/DIO.cpp b/hal/src/main/native/systemcore/DIO.cpp index 46eb679cbbb..64ba27bd371 100644 --- a/hal/src/main/native/systemcore/DIO.cpp +++ b/hal/src/main/native/systemcore/DIO.cpp @@ -201,25 +201,4 @@ HAL_Bool HAL_IsAnyPulsing(int32_t* status) { return false; } -void HAL_SetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t filterIndex, - int32_t* status) { - *status = HAL_HANDLE_ERROR; - return; -} - -int32_t HAL_GetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t* status) { - *status = HAL_HANDLE_ERROR; - return 0; -} - -void HAL_SetFilterPeriod(int32_t filterIndex, int64_t value, int32_t* status) { - *status = HAL_HANDLE_ERROR; - return; -} - -int64_t HAL_GetFilterPeriod(int32_t filterIndex, int32_t* status) { - *status = HAL_HANDLE_ERROR; - return 0; -} - } // extern "C" diff --git a/wpilibc/src/main/native/cpp/DigitalGlitchFilter.cpp b/wpilibc/src/main/native/cpp/DigitalGlitchFilter.cpp deleted file mode 100644 index 44bcabe4636..00000000000 --- a/wpilibc/src/main/native/cpp/DigitalGlitchFilter.cpp +++ /dev/null @@ -1,138 +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. - -#include "frc/DigitalGlitchFilter.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include "frc/Counter.h" -#include "frc/Encoder.h" -#include "frc/Errors.h" -#include "frc/SensorUtil.h" - -using namespace frc; - -std::array DigitalGlitchFilter::m_filterAllocated = { - {false, false, false}}; -wpi::mutex DigitalGlitchFilter::m_mutex; - -DigitalGlitchFilter::DigitalGlitchFilter() { - m_channelIndex = AllocateFilterIndex(); - if (m_channelIndex < 0) { - throw FRC_MakeError(err::NoAvailableResources, - "No filters available to allocate."); - } - HAL_Report(HALUsageReporting::kResourceType_DigitalGlitchFilter, - m_channelIndex + 1); - wpi::SendableRegistry::AddLW(this, "DigitalGlitchFilter", m_channelIndex); -} - -DigitalGlitchFilter::~DigitalGlitchFilter() { - if (m_channelIndex >= 0) { - std::scoped_lock lock(m_mutex); - m_filterAllocated[m_channelIndex] = false; - } -} - -int DigitalGlitchFilter::AllocateFilterIndex() { - std::scoped_lock lock{m_mutex}; - auto filter = - std::find(m_filterAllocated.begin(), m_filterAllocated.end(), false); - - if (filter == m_filterAllocated.end()) { - return -1; - } - *filter = true; - return std::distance(m_filterAllocated.begin(), filter); -} - -void DigitalGlitchFilter::Add(DigitalSource* input) { - DoAdd(input, m_channelIndex + 1); -} - -void DigitalGlitchFilter::DoAdd(DigitalSource* input, int requestedIndex) { - // Some sources from Counters and Encoders are null. By pushing the check - // here, we catch the issue more generally. - if (input) { - // We don't support GlitchFilters on AnalogTriggers. - if (input->IsAnalogTrigger()) { - throw FRC_MakeError( - -1, "Analog Triggers not supported for DigitalGlitchFilters"); - } - int32_t status = 0; - HAL_SetFilterSelect(input->GetPortHandleForRouting(), requestedIndex, - &status); - FRC_CheckErrorStatus(status, "requested index {}", requestedIndex); - - // Validate that we set it correctly. - int actualIndex = - HAL_GetFilterSelect(input->GetPortHandleForRouting(), &status); - FRC_CheckErrorStatus(status, "requested index {}", requestedIndex); - FRC_AssertMessage(actualIndex == requestedIndex, - "HAL_SetFilterSelect({}) failed -> {}", requestedIndex, - actualIndex); - } -} - -void DigitalGlitchFilter::Add(Encoder* input) { - Add(input->m_aSource.get()); - Add(input->m_bSource.get()); -} - -void DigitalGlitchFilter::Add(Counter* input) { - Add(input->m_upSource.get()); - Add(input->m_downSource.get()); -} - -void DigitalGlitchFilter::Remove(DigitalSource* input) { - DoAdd(input, 0); -} - -void DigitalGlitchFilter::Remove(Encoder* input) { - Remove(input->m_aSource.get()); - Remove(input->m_bSource.get()); -} - -void DigitalGlitchFilter::Remove(Counter* input) { - Remove(input->m_upSource.get()); - Remove(input->m_downSource.get()); -} - -void DigitalGlitchFilter::SetPeriodCycles(int fpgaCycles) { - int32_t status = 0; - HAL_SetFilterPeriod(m_channelIndex, fpgaCycles, &status); - FRC_CheckErrorStatus(status, "Channel {}", m_channelIndex); -} - -void DigitalGlitchFilter::SetPeriodNanoSeconds(uint64_t nanoseconds) { - int32_t status = 0; - int fpgaCycles = - nanoseconds * HAL_GetSystemClockTicksPerMicrosecond() / 4 / 1000; - HAL_SetFilterPeriod(m_channelIndex, fpgaCycles, &status); - FRC_CheckErrorStatus(status, "Channel {}", m_channelIndex); -} - -int DigitalGlitchFilter::GetPeriodCycles() { - int32_t status = 0; - int fpgaCycles = HAL_GetFilterPeriod(m_channelIndex, &status); - FRC_CheckErrorStatus(status, "Channel {}", m_channelIndex); - return fpgaCycles; -} - -uint64_t DigitalGlitchFilter::GetPeriodNanoSeconds() { - int32_t status = 0; - int fpgaCycles = HAL_GetFilterPeriod(m_channelIndex, &status); - FRC_CheckErrorStatus(status, "Channel {}", m_channelIndex); - return static_cast(fpgaCycles) * 1000L / - static_cast(HAL_GetSystemClockTicksPerMicrosecond() / 4); -} - -void DigitalGlitchFilter::InitSendable(wpi::SendableBuilder&) {} diff --git a/wpilibc/src/main/native/include/frc/DigitalGlitchFilter.h b/wpilibc/src/main/native/include/frc/DigitalGlitchFilter.h deleted file mode 100644 index 05ddded313b..00000000000 --- a/wpilibc/src/main/native/include/frc/DigitalGlitchFilter.h +++ /dev/null @@ -1,138 +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 "frc/DigitalSource.h" - -namespace frc { - -class Encoder; -class Counter; - -/** - * Class to enable glitch filtering on a set of digital inputs. - * - * This class will manage adding and removing digital inputs from a FPGA glitch - * filter. The filter lets the user configure the time that an input must remain - * high or low before it is classified as high or low. - */ -class DigitalGlitchFilter : public wpi::Sendable, - public wpi::SendableHelper { - public: - DigitalGlitchFilter(); - ~DigitalGlitchFilter() override; - - DigitalGlitchFilter(DigitalGlitchFilter&&) = default; - DigitalGlitchFilter& operator=(DigitalGlitchFilter&&) = default; - - /** - * Assigns the DigitalSource to this glitch filter. - * - * @param input The DigitalSource to add. - */ - void Add(DigitalSource* input); - - /** - * Assigns the Encoder to this glitch filter. - * - * @param input The Encoder to add. - */ - void Add(Encoder* input); - - /** - * Assigns the Counter to this glitch filter. - * - * @param input The Counter to add. - */ - void Add(Counter* input); - - /** - * Removes a digital input from this filter. - * - * Removes the DigitalSource from this glitch filter and re-assigns it to - * the default filter. - * - * @param input The DigitalSource to remove. - */ - void Remove(DigitalSource* input); - - /** - * Removes an encoder from this filter. - * - * Removes the Encoder from this glitch filter and re-assigns it to - * the default filter. - * - * @param input The Encoder to remove. - */ - void Remove(Encoder* input); - - /** - * Removes a counter from this filter. - * - * Removes the Counter from this glitch filter and re-assigns it to - * the default filter. - * - * @param input The Counter to remove. - */ - void Remove(Counter* input); - - /** - * Sets the number of cycles that the input must not change state for. - * - * @param fpgaCycles The number of FPGA cycles. - */ - void SetPeriodCycles(int fpgaCycles); - - /** - * Sets the number of nanoseconds that the input must not change state for. - * - * @param nanoseconds The number of nanoseconds. - */ - void SetPeriodNanoSeconds(uint64_t nanoseconds); - - /** - * Gets the number of cycles that the input must not change state for. - * - * @return The number of cycles. - */ - int GetPeriodCycles(); - - /** - * Gets the number of nanoseconds that the input must not change state for. - * - * @return The number of nanoseconds. - */ - uint64_t GetPeriodNanoSeconds(); - - void InitSendable(wpi::SendableBuilder& builder) override; - - private: - int m_channelIndex; - - // Sets the filter for the input to be the requested index. A value of 0 - // disables the filter, and the filter value must be between 1 and 3, - // inclusive. - static void DoAdd(DigitalSource* input, int requested_index); - - /** - * Allocates the next available filter index, or -1 if there are no filters - * available. - * @return the filter index - */ - static int AllocateFilterIndex(); - - static wpi::mutex m_mutex; - static std::array m_filterAllocated; -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/DigitalInput.h b/wpilibc/src/main/native/include/frc/DigitalInput.h index e850c56ae2c..b53453855d7 100644 --- a/wpilibc/src/main/native/include/frc/DigitalInput.h +++ b/wpilibc/src/main/native/include/frc/DigitalInput.h @@ -12,8 +12,6 @@ namespace frc { -class DigitalGlitchFilter; - /** * Class to read a digital input. * @@ -81,8 +79,6 @@ class DigitalInput : public DigitalSource, private: int m_channel; hal::Handle m_handle; - - friend class DigitalGlitchFilter; }; } // namespace frc diff --git a/wpilibc/src/main/native/include/frc/Encoder.h b/wpilibc/src/main/native/include/frc/Encoder.h index 82d7d3409d1..f05c33cc048 100644 --- a/wpilibc/src/main/native/include/frc/Encoder.h +++ b/wpilibc/src/main/native/include/frc/Encoder.h @@ -17,7 +17,6 @@ namespace frc { class DigitalSource; -class DigitalGlitchFilter; /** * Class to read quad encoders. @@ -375,8 +374,6 @@ class Encoder : public CounterBase, std::shared_ptr m_bSource; // The B phase of the quad encoder std::shared_ptr m_indexSource = nullptr; hal::Handle m_encoder; - - friend class DigitalGlitchFilter; }; } // namespace frc diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalGlitchFilter.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalGlitchFilter.java deleted file mode 100644 index 9d3086e9526..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalGlitchFilter.java +++ /dev/null @@ -1,192 +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. - -package edu.wpi.first.wpilibj; - -import edu.wpi.first.hal.DigitalGlitchFilterJNI; -import edu.wpi.first.hal.FRCNetComm.tResourceType; -import edu.wpi.first.hal.HAL; -import edu.wpi.first.hal.util.AllocationException; -import edu.wpi.first.util.sendable.Sendable; -import edu.wpi.first.util.sendable.SendableBuilder; -import edu.wpi.first.util.sendable.SendableRegistry; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Class to enable glitch filtering on a set of digital inputs. This class will manage adding and - * removing digital inputs from an FPGA glitch filter. The filter lets the user configure the time - * that an input must remain high or low before it is classified as high or low. - */ -public class DigitalGlitchFilter implements Sendable, AutoCloseable { - /** Configures the Digital Glitch Filter to its default settings. */ - @SuppressWarnings("this-escape") - public DigitalGlitchFilter() { - m_channelIndex = allocateFilterIndex(); - if (m_channelIndex < 0) { - throw new AllocationException("No filters available to allocate."); - } - HAL.report(tResourceType.kResourceType_DigitalGlitchFilter, m_channelIndex + 1, 0); - SendableRegistry.addLW(this, "DigitalGlitchFilter", m_channelIndex); - } - - @Override - public void close() { - SendableRegistry.remove(this); - if (m_channelIndex >= 0) { - m_mutex.lock(); - try { - m_filterAllocated[m_channelIndex] = false; - } finally { - m_mutex.unlock(); - } - - m_channelIndex = -1; - } - } - - /** - * Allocates the next available filter index, or -1 if there are no filters available. - * - * @return the filter index - */ - private static int allocateFilterIndex() { - m_mutex.lock(); - try { - for (int index = 0; index < m_filterAllocated.length; index++) { - if (!m_filterAllocated[index]) { - m_filterAllocated[index] = true; - return index; - } - } - } finally { - m_mutex.unlock(); - } - return -1; - } - - private static void setFilter(DigitalSource input, int channelIndex) { - if (input != null) { // Counter might have just one input - // analog triggers are not supported for DigitalGlitchFilters - if (input.isAnalogTrigger()) { - throw new IllegalStateException("Analog Triggers not supported for DigitalGlitchFilters"); - } - DigitalGlitchFilterJNI.setFilterSelect(input.getPortHandleForRouting(), channelIndex); - - int selected = DigitalGlitchFilterJNI.getFilterSelect(input.getPortHandleForRouting()); - if (selected != channelIndex) { - throw new IllegalStateException( - "DigitalGlitchFilterJNI.setFilterSelect(" + channelIndex + ") failed -> " + selected); - } - } - } - - /** - * Assigns the DigitalSource to this glitch filter. - * - * @param input The DigitalSource to add. - */ - public void add(DigitalSource input) { - setFilter(input, m_channelIndex + 1); - } - - /** - * Assigns the Encoder to this glitch filter. - * - * @param input The Encoder to add. - */ - public void add(Encoder input) { - add(input.m_aSource); - add(input.m_bSource); - } - - /** - * Assigns the Counter to this glitch filter. - * - * @param input The Counter to add. - */ - public void add(Counter input) { - add(input.m_upSource); - add(input.m_downSource); - } - - /** - * Removes this filter from the given digital input. - * - * @param input The DigitalSource to stop filtering. - */ - public void remove(DigitalSource input) { - setFilter(input, 0); - } - - /** - * Removes this filter from the given Encoder. - * - * @param input the Encoder to stop filtering. - */ - public void remove(Encoder input) { - remove(input.m_aSource); - remove(input.m_bSource); - } - - /** - * Removes this filter from the given Counter. - * - * @param input The Counter to stop filtering. - */ - public void remove(Counter input) { - remove(input.m_upSource); - remove(input.m_downSource); - } - - /** - * Sets the number of FPGA cycles that the input must hold steady to pass through this glitch - * filter. - * - * @param fpgaCycles The number of FPGA cycles. - */ - public void setPeriodCycles(int fpgaCycles) { - DigitalGlitchFilterJNI.setFilterPeriod(m_channelIndex, fpgaCycles); - } - - /** - * Sets the number of nanoseconds that the input must hold steady to pass through this glitch - * filter. - * - * @param nanoseconds The number of nanoseconds. - */ - public void setPeriodNanoSeconds(long nanoseconds) { - int fpgaCycles = (int) (nanoseconds * SensorUtil.kSystemClockTicksPerMicrosecond / 4 / 1000); - setPeriodCycles(fpgaCycles); - } - - /** - * Gets the number of FPGA cycles that the input must hold steady to pass through this glitch - * filter. - * - * @return The number of cycles. - */ - public int getPeriodCycles() { - return DigitalGlitchFilterJNI.getFilterPeriod(m_channelIndex); - } - - /** - * Gets the number of nanoseconds that the input must hold steady to pass through this glitch - * filter. - * - * @return The number of nanoseconds. - */ - public long getPeriodNanoSeconds() { - int fpgaCycles = getPeriodCycles(); - - return fpgaCycles * 1000L / (SensorUtil.kSystemClockTicksPerMicrosecond / 4); - } - - @Override - public void initSendable(SendableBuilder builder) {} - - private int m_channelIndex; - private static final Lock m_mutex = new ReentrantLock(true); - private static final boolean[] m_filterAllocated = new boolean[3]; -} From 5898cdd5c3443517ed4a9095469ec8b76203b763 Mon Sep 17 00:00:00 2001 From: Thad House Date: Thu, 23 Jan 2025 21:45:18 -0800 Subject: [PATCH 2/6] [hal, wpilib] Remove interrupt (#7724) --- .../java/edu/wpi/first/hal/InterruptJNI.java | 120 ----- hal/src/main/native/cpp/jni/InterruptJNI.cpp | 173 ------- hal/src/main/native/include/hal/HAL.h | 1 - hal/src/main/native/include/hal/Interrupts.h | 137 ------ hal/src/main/native/sim/HAL.cpp | 1 - hal/src/main/native/sim/HALInitializer.h | 1 - hal/src/main/native/sim/Interrupts.cpp | 454 ------------------ hal/src/main/native/systemcore/HAL.cpp | 1 - .../main/native/systemcore/HALInitializer.h | 2 - hal/src/main/native/systemcore/Interrupts.cpp | 83 ---- .../main/native/cpp/AsynchronousInterrupt.cpp | 70 --- .../main/native/cpp/SynchronousInterrupt.cpp | 103 ---- .../include/frc/AsynchronousInterrupt.h | 180 ------- .../native/include/frc/SynchronousInterrupt.h | 112 ----- wpilibc/src/test/native/cpp/InterruptTest.cpp | 103 ---- .../first/wpilibj/AsynchronousInterrupt.java | 155 ------ .../first/wpilibj/SynchronousInterrupt.java | 154 ------ .../edu/wpi/first/wpilibj/InterruptTest.java | 120 ----- 18 files changed, 1970 deletions(-) delete mode 100644 hal/src/main/java/edu/wpi/first/hal/InterruptJNI.java delete mode 100644 hal/src/main/native/cpp/jni/InterruptJNI.cpp delete mode 100644 hal/src/main/native/include/hal/Interrupts.h delete mode 100644 hal/src/main/native/sim/Interrupts.cpp delete mode 100644 hal/src/main/native/systemcore/Interrupts.cpp delete mode 100644 wpilibc/src/main/native/cpp/AsynchronousInterrupt.cpp delete mode 100644 wpilibc/src/main/native/cpp/SynchronousInterrupt.cpp delete mode 100644 wpilibc/src/main/native/include/frc/AsynchronousInterrupt.h delete mode 100644 wpilibc/src/main/native/include/frc/SynchronousInterrupt.h delete mode 100644 wpilibc/src/test/native/cpp/InterruptTest.cpp delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/AsynchronousInterrupt.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/SynchronousInterrupt.java delete mode 100644 wpilibj/src/test/java/edu/wpi/first/wpilibj/InterruptTest.java diff --git a/hal/src/main/java/edu/wpi/first/hal/InterruptJNI.java b/hal/src/main/java/edu/wpi/first/hal/InterruptJNI.java deleted file mode 100644 index 0ef806e4342..00000000000 --- a/hal/src/main/java/edu/wpi/first/hal/InterruptJNI.java +++ /dev/null @@ -1,120 +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. - -package edu.wpi.first.hal; - -/** - * Interrupt HAL JNI functions. - * - * @see "hal/Interrupts.h" - */ -public class InterruptJNI extends JNIWrapper { - /** Invalid handle value. */ - public static final int HalInvalidHandle = 0; - - /** - * Initializes an interrupt. - * - * @return the created interrupt handle - * @see "HAL_InitializeInterrupts" - */ - public static native int initializeInterrupts(); - - /** - * Frees an interrupt. - * - * @param interruptHandle the interrupt handle - * @see "HAL_CleanInterrupts" - */ - public static native void cleanInterrupts(int interruptHandle); - - /** - * Waits for the defined interrupt to occur. - * - * @param interruptHandle the interrupt handle - * @param timeout timeout in seconds - * @param ignorePrevious if true, ignore interrupts that happened before waitForInterrupt was - * called - * @return the mask of interrupts that fired - * @see "HAL_WaitForInterrupt" - */ - public static native long waitForInterrupt( - int interruptHandle, double timeout, boolean ignorePrevious); - - /** - * Waits for any interrupt covered by the mask to occur. - * - * @param interruptHandle the interrupt handle to use for the context - * @param mask the mask of interrupts to wait for - * @param timeout timeout in seconds - * @param ignorePrevious if true, ignore interrupts that happened before waitForInterrupt was - * called - * @return the mask of interrupts that fired - * @see "HAL_WaitForMultipleInterrupts" - */ - public static native long waitForMultipleInterrupts( - int interruptHandle, long mask, double timeout, boolean ignorePrevious); - - /** - * Returns the timestamp for the rising interrupt that occurred most recently. - * - *

This is in the same time domain as getFPGATime(). It only contains the bottom 32 bits of the - * timestamp. If your robot has been running for over 1 hour, you will need to fill in the upper - * 32 bits yourself. - * - * @param interruptHandle the interrupt handle - * @return timestamp in microseconds since FPGA Initialization - */ - public static native long readInterruptRisingTimestamp(int interruptHandle); - - /** - * Returns the timestamp for the falling interrupt that occurred most recently. - * - *

This is in the same time domain as getFPGATime(). It only contains the bottom 32 bits of the - * timestamp. If your robot has been running for over 1 hour, you will need to fill in the upper - * 32 bits yourself. - * - * @param interruptHandle the interrupt handle - * @return timestamp in microseconds since FPGA Initialization - */ - public static native long readInterruptFallingTimestamp(int interruptHandle); - - /** - * Requests interrupts on a specific digital source. - * - * @param interruptHandle the interrupt handle - * @param digitalSourceHandle the digital source handle (either a HAL_AnalogTriggerHandle or a - * HAL_DigitalHandle) - * @param analogTriggerType the trigger type if the source is an AnalogTrigger - * @see "HAL_RequestInterrupts" - */ - public static native void requestInterrupts( - int interruptHandle, int digitalSourceHandle, int analogTriggerType); - - /** - * Sets the edges to trigger the interrupt on. - * - *

Note that both edges triggered is a valid configuration. - * - * @param interruptHandle the interrupt handle - * @param risingEdge true for triggering on rising edge - * @param fallingEdge true for triggering on falling edge - * @see "HAL_SetInterruptUpSourceEdge" - */ - public static native void setInterruptUpSourceEdge( - int interruptHandle, boolean risingEdge, boolean fallingEdge); - - /** - * Releases a waiting interrupt. - * - *

This will release both rising and falling waiters. - * - * @param interruptHandle the interrupt handle to release - * @see "HAL_ReleaseWaitingInterrupt" - */ - public static native void releaseWaitingInterrupt(int interruptHandle); - - /** Utility class. */ - private InterruptJNI() {} -} diff --git a/hal/src/main/native/cpp/jni/InterruptJNI.cpp b/hal/src/main/native/cpp/jni/InterruptJNI.cpp deleted file mode 100644 index 3654cb8ac10..00000000000 --- a/hal/src/main/native/cpp/jni/InterruptJNI.cpp +++ /dev/null @@ -1,173 +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. - -#include - -#include -#include -#include - -#include -#include - -#include "HALUtil.h" -#include "edu_wpi_first_hal_InterruptJNI.h" -#include "hal/Interrupts.h" - -using namespace hal; - -extern "C" { - -/* - * Class: edu_wpi_first_hal_InterruptJNI - * Method: initializeInterrupts - * Signature: ()I - */ -JNIEXPORT jint JNICALL -Java_edu_wpi_first_hal_InterruptJNI_initializeInterrupts - (JNIEnv* env, jclass) -{ - int32_t status = 0; - HAL_InterruptHandle interrupt = HAL_InitializeInterrupts(&status); - - CheckStatusForceThrow(env, status); - return (jint)interrupt; -} - -/* - * Class: edu_wpi_first_hal_InterruptJNI - * Method: cleanInterrupts - * Signature: (I)V - */ -JNIEXPORT void JNICALL -Java_edu_wpi_first_hal_InterruptJNI_cleanInterrupts - (JNIEnv* env, jclass, jint interruptHandle) -{ - if (interruptHandle != HAL_kInvalidHandle) { - HAL_CleanInterrupts((HAL_InterruptHandle)interruptHandle); - } -} - -/* - * Class: edu_wpi_first_hal_InterruptJNI - * Method: waitForInterrupt - * Signature: (IDZ)J - */ -JNIEXPORT jlong JNICALL -Java_edu_wpi_first_hal_InterruptJNI_waitForInterrupt - (JNIEnv* env, jclass, jint interruptHandle, jdouble timeout, - jboolean ignorePrevious) -{ - int32_t status = 0; - int64_t result = HAL_WaitForInterrupt((HAL_InterruptHandle)interruptHandle, - timeout, ignorePrevious, &status); - - CheckStatus(env, status); - return result; -} - -/* - * Class: edu_wpi_first_hal_InterruptJNI - * Method: waitForMultipleInterrupts - * Signature: (IJDZ)J - */ -JNIEXPORT jlong JNICALL -Java_edu_wpi_first_hal_InterruptJNI_waitForMultipleInterrupts - (JNIEnv* env, jclass, jint interruptHandle, jlong mask, jdouble timeout, - jboolean ignorePrevious) -{ - int32_t status = 0; - int64_t result = - HAL_WaitForMultipleInterrupts((HAL_InterruptHandle)interruptHandle, mask, - timeout, ignorePrevious, &status); - - CheckStatus(env, status); - return result; -} - -/* - * Class: edu_wpi_first_hal_InterruptJNI - * Method: readInterruptRisingTimestamp - * Signature: (I)J - */ -JNIEXPORT jlong JNICALL -Java_edu_wpi_first_hal_InterruptJNI_readInterruptRisingTimestamp - (JNIEnv* env, jclass, jint interruptHandle) -{ - int32_t status = 0; - jlong timeStamp = HAL_ReadInterruptRisingTimestamp( - (HAL_InterruptHandle)interruptHandle, &status); - - CheckStatus(env, status); - return timeStamp; -} - -/* - * Class: edu_wpi_first_hal_InterruptJNI - * Method: readInterruptFallingTimestamp - * Signature: (I)J - */ -JNIEXPORT jlong JNICALL -Java_edu_wpi_first_hal_InterruptJNI_readInterruptFallingTimestamp - (JNIEnv* env, jclass, jint interruptHandle) -{ - int32_t status = 0; - jlong timeStamp = HAL_ReadInterruptFallingTimestamp( - (HAL_InterruptHandle)interruptHandle, &status); - - CheckStatus(env, status); - return timeStamp; -} - -/* - * Class: edu_wpi_first_hal_InterruptJNI - * Method: requestInterrupts - * Signature: (III)V - */ -JNIEXPORT void JNICALL -Java_edu_wpi_first_hal_InterruptJNI_requestInterrupts - (JNIEnv* env, jclass, jint interruptHandle, jint digitalSourceHandle, - jint analogTriggerType) -{ - int32_t status = 0; - HAL_RequestInterrupts((HAL_InterruptHandle)interruptHandle, - (HAL_Handle)digitalSourceHandle, - (HAL_AnalogTriggerType)analogTriggerType, &status); - - CheckStatus(env, status); -} - -/* - * Class: edu_wpi_first_hal_InterruptJNI - * Method: setInterruptUpSourceEdge - * Signature: (IZZ)V - */ -JNIEXPORT void JNICALL -Java_edu_wpi_first_hal_InterruptJNI_setInterruptUpSourceEdge - (JNIEnv* env, jclass, jint interruptHandle, jboolean risingEdge, - jboolean fallingEdge) -{ - int32_t status = 0; - HAL_SetInterruptUpSourceEdge((HAL_InterruptHandle)interruptHandle, risingEdge, - fallingEdge, &status); - - CheckStatus(env, status); -} - -/* - * Class: edu_wpi_first_hal_InterruptJNI - * Method: releaseWaitingInterrupt - * Signature: (I)V - */ -JNIEXPORT void JNICALL -Java_edu_wpi_first_hal_InterruptJNI_releaseWaitingInterrupt - (JNIEnv* env, jclass, jint interruptHandle) -{ - int32_t status = 0; - HAL_ReleaseWaitingInterrupt((HAL_InterruptHandle)interruptHandle, &status); - - CheckStatus(env, status); -} - -} // extern "C" diff --git a/hal/src/main/native/include/hal/HAL.h b/hal/src/main/native/include/hal/HAL.h index 4072b4a64d6..d44470ce737 100644 --- a/hal/src/main/native/include/hal/HAL.h +++ b/hal/src/main/native/include/hal/HAL.h @@ -20,7 +20,6 @@ #include "hal/FRCUsageReporting.h" #include "hal/HALBase.h" #include "hal/I2C.h" -#include "hal/Interrupts.h" #include "hal/LEDs.h" #include "hal/Main.h" #include "hal/Notifier.h" diff --git a/hal/src/main/native/include/hal/Interrupts.h b/hal/src/main/native/include/hal/Interrupts.h deleted file mode 100644 index 2bccbe9ce4d..00000000000 --- a/hal/src/main/native/include/hal/Interrupts.h +++ /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. - -#pragma once - -#include - -#include "hal/AnalogTrigger.h" -#include "hal/Types.h" - -/** - * @defgroup hal_interrupts Interrupts Functions - * @ingroup hal_capi - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Initializes an interrupt. - * - * @param[out] status Error status variable. 0 on success. - * @return the created interrupt handle - */ -HAL_InterruptHandle HAL_InitializeInterrupts(int32_t* status); - -/** - * Frees an interrupt. - * - * @param interruptHandle the interrupt handle - */ -void HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle); - -/** - * Waits for the defined interrupt to occur. - * - * @param[in] interruptHandle the interrupt handle - * @param[in] timeout timeout in seconds - * @param[in] ignorePrevious if true, ignore interrupts that happened before - * waitForInterrupt was called - * @param[out] status Error status variable. 0 on success. - * @return the mask of interrupts that fired - */ -int64_t HAL_WaitForInterrupt(HAL_InterruptHandle interruptHandle, - double timeout, HAL_Bool ignorePrevious, - int32_t* status); - -/** - * Waits for any interrupt covered by the mask to occur. - * - * @param[in] interruptHandle the interrupt handle to use for the context - * @param[in] mask the mask of interrupts to wait for - * @param[in] timeout timeout in seconds - * @param[in] ignorePrevious if true, ignore interrupts that happened before - * waitForInterrupt was called - * @param[out] status Error status variable. 0 on success. - * @return the mask of interrupts that fired - */ -int64_t HAL_WaitForMultipleInterrupts(HAL_InterruptHandle interruptHandle, - int64_t mask, double timeout, - HAL_Bool ignorePrevious, int32_t* status); - -/** - * Returns the timestamp for the rising interrupt that occurred most recently. - * - * This is in the same time domain as HAL_GetFPGATime(). It only contains the - * bottom 32 bits of the timestamp. If your robot has been running for over 1 - * hour, you will need to fill in the upper 32 bits yourself. - * - * @param[in] interruptHandle the interrupt handle - * @param[out] status Error status variable. 0 on success. - * @return timestamp in microseconds since FPGA Initialization - */ -int64_t HAL_ReadInterruptRisingTimestamp(HAL_InterruptHandle interruptHandle, - int32_t* status); - -/** - * Returns the timestamp for the falling interrupt that occurred most recently. - * - * This is in the same time domain as HAL_GetFPGATime(). It only contains the - * bottom 32 bits of the timestamp. If your robot has been running for over 1 - * hour, you will need to fill in the upper 32 bits yourself. - * - * @param[in] interruptHandle the interrupt handle - * @param[out] status Error status variable. 0 on success. - * @return timestamp in microseconds since FPGA Initialization - */ -int64_t HAL_ReadInterruptFallingTimestamp(HAL_InterruptHandle interruptHandle, - int32_t* status); - -/** - * Requests interrupts on a specific digital source. - * - * @param[in] interruptHandle the interrupt handle - * @param[in] digitalSourceHandle the digital source handle (either a - * HAL_AnalogTriggerHandle or a - * HAL_DigitalHandle) - * @param[in] analogTriggerType the trigger type if the source is an - * AnalogTrigger - * @param[out] status Error status variable. 0 on success. - */ -void HAL_RequestInterrupts(HAL_InterruptHandle interruptHandle, - HAL_Handle digitalSourceHandle, - HAL_AnalogTriggerType analogTriggerType, - int32_t* status); - -/** - * Sets the edges to trigger the interrupt on. - * - * Note that both edges triggered is a valid configuration. - * - * @param[in] interruptHandle the interrupt handle - * @param[in] risingEdge true for triggering on rising edge - * @param[in] fallingEdge true for triggering on falling edge - * @param[out] status Error status variable. 0 on success. - */ -void HAL_SetInterruptUpSourceEdge(HAL_InterruptHandle interruptHandle, - HAL_Bool risingEdge, HAL_Bool fallingEdge, - int32_t* status); - -/** - * Releases a waiting interrupt. - * - * This will release both rising and falling waiters. - * - * @param[in] interruptHandle the interrupt handle to release - * @param[out] status Error status variable. 0 on success. - */ -void HAL_ReleaseWaitingInterrupt(HAL_InterruptHandle interruptHandle, - int32_t* status); -#ifdef __cplusplus -} // extern "C" -#endif -/** @} */ diff --git a/hal/src/main/native/sim/HAL.cpp b/hal/src/main/native/sim/HAL.cpp index 26e97c68294..3227d886947 100644 --- a/hal/src/main/native/sim/HAL.cpp +++ b/hal/src/main/native/sim/HAL.cpp @@ -97,7 +97,6 @@ void InitializeHAL() { InitializeEncoder(); InitializeExtensions(); InitializeI2C(); - InitializeInterrupts(); InitializeMain(); InitializeMockHooks(); InitializeNotifier(); diff --git a/hal/src/main/native/sim/HALInitializer.h b/hal/src/main/native/sim/HALInitializer.h index 53841bbe452..359bce8542e 100644 --- a/hal/src/main/native/sim/HALInitializer.h +++ b/hal/src/main/native/sim/HALInitializer.h @@ -48,7 +48,6 @@ extern void InitializeEncoder(); extern void InitializeExtensions(); extern void InitializeHAL(); extern void InitializeI2C(); -extern void InitializeInterrupts(); extern void InitializeMain(); extern void InitializeMockHooks(); extern void InitializeNotifier(); diff --git a/hal/src/main/native/sim/Interrupts.cpp b/hal/src/main/native/sim/Interrupts.cpp deleted file mode 100644 index 1537c73640a..00000000000 --- a/hal/src/main/native/sim/Interrupts.cpp +++ /dev/null @@ -1,454 +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. - -#include "hal/Interrupts.h" - -#include - -#include - -#include "AnalogInternal.h" -#include "DigitalInternal.h" -#include "ErrorsInternal.h" -#include "HALInitializer.h" -#include "MockHooksInternal.h" -#include "PortsInternal.h" -#include "hal/AnalogTrigger.h" -#include "hal/Errors.h" -#include "hal/Value.h" -#include "hal/handles/HandlesInternal.h" -#include "hal/handles/LimitedHandleResource.h" -#include "hal/handles/UnlimitedHandleResource.h" -#include "mockdata/AnalogInDataInternal.h" -#include "mockdata/DIODataInternal.h" - -#ifdef _WIN32 -#pragma warning(disable : 4996 4018 6297 26451 4334) -#endif - -using namespace hal; - -enum WaitResult { - Timeout = 0x0, - RisingEdge = 0x1, - FallingEdge = 0x100, - Both = 0x101, -}; - -namespace { -struct Interrupt { - bool isAnalog; - HAL_Handle portHandle; - uint8_t index; - HAL_AnalogTriggerType trigType; - int64_t risingTimestamp; - int64_t fallingTimestamp; - bool currentState; - bool fireOnUp; - bool fireOnDown; - int32_t callbackId; -}; - -struct SynchronousWaitData { - HAL_InterruptHandle interruptHandle{HAL_kInvalidHandle}; - wpi::condition_variable waitCond; - HAL_Bool waitPredicate{false}; -}; -} // namespace - -static LimitedHandleResource* interruptHandles; - -using SynchronousWaitDataHandle = HAL_Handle; -static UnlimitedHandleResource* - synchronousInterruptHandles; - -namespace hal::init { -void InitializeInterrupts() { - static LimitedHandleResource - iH; - interruptHandles = &iH; - static UnlimitedHandleResource - siH; - synchronousInterruptHandles = &siH; -} -} // namespace hal::init - -extern "C" { -HAL_InterruptHandle HAL_InitializeInterrupts(int32_t* status) { - hal::init::CheckInit(); - HAL_InterruptHandle handle = interruptHandles->Allocate(); - if (handle == HAL_kInvalidHandle) { - *status = NO_AVAILABLE_RESOURCES; - return HAL_kInvalidHandle; - } - auto anInterrupt = interruptHandles->Get(handle); - if (anInterrupt == nullptr) { // would only occur on thread issue. - *status = HAL_HANDLE_ERROR; - return HAL_kInvalidHandle; - } - - anInterrupt->index = getHandleIndex(handle); - anInterrupt->callbackId = -1; - - return handle; -} -void HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle) { - interruptHandles->Free(interruptHandle); -} - -static void ProcessInterruptDigitalSynchronous(const char* name, void* param, - const struct HAL_Value* value) { - // void* is a SynchronousWaitDataHandle. - // convert to uintptr_t first, then to handle - uintptr_t handleTmp = reinterpret_cast(param); - SynchronousWaitDataHandle handle = - static_cast(handleTmp); - auto interruptData = synchronousInterruptHandles->Get(handle); - if (interruptData == nullptr) { - return; - } - auto interrupt = interruptHandles->Get(interruptData->interruptHandle); - if (interrupt == nullptr) { - return; - } - // Have a valid interrupt - if (value->type != HAL_Type::HAL_BOOLEAN) { - return; - } - bool retVal = value->data.v_boolean; - auto previousState = interrupt->currentState; - interrupt->currentState = retVal; - // If no change in interrupt, return; - if (retVal == previousState) { - return; - } - // If its a falling change, and we dont fire on falling return - if (previousState && !interrupt->fireOnDown) { - return; - } - // If its a rising change, and we dont fire on rising return. - if (!previousState && !interrupt->fireOnUp) { - return; - } - - interruptData->waitPredicate = true; - - // Pulse interrupt - interruptData->waitCond.notify_all(); -} - -static double GetAnalogTriggerValue(HAL_Handle triggerHandle, - HAL_AnalogTriggerType type, - int32_t* status) { - return HAL_GetAnalogTriggerOutput(triggerHandle, type, status); -} - -static void ProcessInterruptAnalogSynchronous(const char* name, void* param, - const struct HAL_Value* value) { - // void* is a SynchronousWaitDataHandle. - // convert to uintptr_t first, then to handle - uintptr_t handleTmp = reinterpret_cast(param); - SynchronousWaitDataHandle handle = - static_cast(handleTmp); - auto interruptData = synchronousInterruptHandles->Get(handle); - if (interruptData == nullptr) { - return; - } - auto interrupt = interruptHandles->Get(interruptData->interruptHandle); - if (interrupt == nullptr) { - return; - } - // Have a valid interrupt - if (value->type != HAL_Type::HAL_DOUBLE) { - return; - } - int32_t status = 0; - bool retVal = GetAnalogTriggerValue(interrupt->portHandle, - interrupt->trigType, &status); - if (status != 0) { - // Interrupt and Cancel - interruptData->waitPredicate = true; - // Pulse interrupt - interruptData->waitCond.notify_all(); - } - auto previousState = interrupt->currentState; - interrupt->currentState = retVal; - // If no change in interrupt, return; - if (retVal == previousState) { - return; - } - // If its a falling change, and we dont fire on falling return - if (previousState && !interrupt->fireOnDown) { - return; - } - // If its a rising change, and we dont fire on rising return. - if (!previousState && !interrupt->fireOnUp) { - return; - } - - interruptData->waitPredicate = true; - - // Pulse interrupt - interruptData->waitCond.notify_all(); -} - -static int64_t WaitForInterruptDigital(HAL_InterruptHandle handle, - Interrupt* interrupt, double timeout, - bool ignorePrevious) { - auto data = std::make_shared(); - - auto dataHandle = synchronousInterruptHandles->Allocate(data); - if (dataHandle == HAL_kInvalidHandle) { - // Error allocating data - return WaitResult::Timeout; - } - - // auto data = synchronousInterruptHandles->Get(dataHandle); - data->waitPredicate = false; - data->interruptHandle = handle; - - int32_t status = 0; - - int32_t digitalIndex = GetDigitalInputChannel(interrupt->portHandle, &status); - - if (status != 0) { - return WaitResult::Timeout; - } - - interrupt->currentState = SimDIOData[digitalIndex].value; - - int32_t uid = SimDIOData[digitalIndex].value.RegisterCallback( - &ProcessInterruptDigitalSynchronous, - reinterpret_cast(static_cast(dataHandle)), false); - - bool timedOut = false; - - wpi::mutex waitMutex; - - auto timeoutTime = - std::chrono::steady_clock::now() + std::chrono::duration(timeout); - - { - std::unique_lock lock(waitMutex); - while (!data->waitPredicate) { - if (data->waitCond.wait_until(lock, timeoutTime) == - std::cv_status::timeout) { - timedOut = true; - break; - } - } - } - - // Cancel our callback - SimDIOData[digitalIndex].value.CancelCallback(uid); - (void)synchronousInterruptHandles->Free(dataHandle); - - // Check for what to return - if (timedOut) { - return WaitResult::Timeout; - } - // We know the value has changed because we would've timed out otherwise. - // If the current state is true, the previous state was false, so this is a - // rising edge. Otherwise, it's a falling edge. - if (interrupt->currentState) { - // Set our return value and our timestamps - interrupt->risingTimestamp = hal::GetFPGATime(); - return 1 << (interrupt->index); - } else { - interrupt->fallingTimestamp = hal::GetFPGATime(); - return 1 << (8 + interrupt->index); - } -} - -static int64_t WaitForInterruptAnalog(HAL_InterruptHandle handle, - Interrupt* interrupt, double timeout, - bool ignorePrevious) { - auto data = std::make_shared(); - - auto dataHandle = synchronousInterruptHandles->Allocate(data); - if (dataHandle == HAL_kInvalidHandle) { - // Error allocating data - return WaitResult::Timeout; - } - - data->waitPredicate = false; - data->interruptHandle = handle; - - int32_t status = 0; - interrupt->currentState = GetAnalogTriggerValue(interrupt->portHandle, - interrupt->trigType, &status); - - if (status != 0) { - return WaitResult::Timeout; - } - - int32_t analogIndex = - GetAnalogTriggerInputIndex(interrupt->portHandle, &status); - - if (status != 0) { - return WaitResult::Timeout; - } - - int32_t uid = SimAnalogInData[analogIndex].voltage.RegisterCallback( - &ProcessInterruptAnalogSynchronous, - reinterpret_cast(static_cast(dataHandle)), false); - - bool timedOut = false; - - wpi::mutex waitMutex; - - auto timeoutTime = - std::chrono::steady_clock::now() + std::chrono::duration(timeout); - - { - std::unique_lock lock(waitMutex); - while (!data->waitPredicate) { - if (data->waitCond.wait_until(lock, timeoutTime) == - std::cv_status::timeout) { - timedOut = true; - break; - } - } - } - - // Cancel our callback - SimAnalogInData[analogIndex].voltage.CancelCallback(uid); - (void)synchronousInterruptHandles->Free(dataHandle); - - // Check for what to return - if (timedOut) { - return WaitResult::Timeout; - } - // We know the value has changed because we would've timed out otherwise. - // If the current state is true, the previous state was false, so this is a - // rising edge. Otherwise, it's a falling edge. - if (interrupt->currentState) { - // Set our return value and our timestamps - interrupt->risingTimestamp = hal::GetFPGATime(); - return 1 << (interrupt->index); - } else { - interrupt->fallingTimestamp = hal::GetFPGATime(); - return 1 << (8 + interrupt->index); - } -} - -int64_t HAL_WaitForInterrupt(HAL_InterruptHandle interruptHandle, - double timeout, HAL_Bool ignorePrevious, - int32_t* status) { - auto interrupt = interruptHandles->Get(interruptHandle); - if (interrupt == nullptr) { - *status = HAL_HANDLE_ERROR; - return WaitResult::Timeout; - } - - if (interrupt->isAnalog) { - return WaitForInterruptAnalog(interruptHandle, interrupt.get(), timeout, - ignorePrevious); - } else { - return WaitForInterruptDigital(interruptHandle, interrupt.get(), timeout, - ignorePrevious); - } -} - -int64_t HAL_WaitForMultipleInterrupts(HAL_InterruptHandle interruptHandle, - int64_t mask, double timeout, - HAL_Bool ignorePrevious, - int32_t* status) { - // TODO make this properly work, will require a decent rewrite - auto interrupt = interruptHandles->Get(interruptHandle); - if (interrupt == nullptr) { - *status = HAL_HANDLE_ERROR; - return WaitResult::Timeout; - } - - if (interrupt->isAnalog) { - return WaitForInterruptAnalog(interruptHandle, interrupt.get(), timeout, - ignorePrevious); - } else { - return WaitForInterruptDigital(interruptHandle, interrupt.get(), timeout, - ignorePrevious); - } -} - -int64_t HAL_ReadInterruptRisingTimestamp(HAL_InterruptHandle interruptHandle, - int32_t* status) { - auto interrupt = interruptHandles->Get(interruptHandle); - if (interrupt == nullptr) { - *status = HAL_HANDLE_ERROR; - return 0; - } - - return interrupt->risingTimestamp; -} -int64_t HAL_ReadInterruptFallingTimestamp(HAL_InterruptHandle interruptHandle, - int32_t* status) { - auto interrupt = interruptHandles->Get(interruptHandle); - if (interrupt == nullptr) { - *status = HAL_HANDLE_ERROR; - return 0; - } - - return interrupt->fallingTimestamp; -} -void HAL_RequestInterrupts(HAL_InterruptHandle interruptHandle, - HAL_Handle digitalSourceHandle, - HAL_AnalogTriggerType analogTriggerType, - int32_t* status) { - auto interrupt = interruptHandles->Get(interruptHandle); - if (interrupt == nullptr) { - *status = HAL_HANDLE_ERROR; - return; - } - - bool routingAnalogTrigger = false; - uint8_t routingChannel = 0; - uint8_t routingModule = 0; - bool success = - remapDigitalSource(digitalSourceHandle, analogTriggerType, routingChannel, - routingModule, routingAnalogTrigger); - if (!success) { - *status = HAL_HANDLE_ERROR; - return; - } - - interrupt->isAnalog = routingAnalogTrigger; - interrupt->trigType = analogTriggerType; - interrupt->portHandle = digitalSourceHandle; -} - -void HAL_SetInterruptUpSourceEdge(HAL_InterruptHandle interruptHandle, - HAL_Bool risingEdge, HAL_Bool fallingEdge, - int32_t* status) { - auto interrupt = interruptHandles->Get(interruptHandle); - if (interrupt == nullptr) { - *status = HAL_HANDLE_ERROR; - return; - } - - interrupt->fireOnDown = fallingEdge; - interrupt->fireOnUp = risingEdge; -} - -void HAL_ReleaseWaitingInterrupt(HAL_InterruptHandle interruptHandle, - int32_t* status) { - auto interrupt = interruptHandles->Get(interruptHandle); - if (interrupt == nullptr) { - *status = HAL_HANDLE_ERROR; - return; - } - - synchronousInterruptHandles->ForEach( - [interruptHandle](SynchronousWaitDataHandle handle, - SynchronousWaitData* data) { - if (data->interruptHandle == interruptHandle) { - data->waitPredicate = true; - data->waitCond.notify_all(); - } - }); -} -} // extern "C" diff --git a/hal/src/main/native/systemcore/HAL.cpp b/hal/src/main/native/systemcore/HAL.cpp index 0e347c3bef0..5680014f386 100644 --- a/hal/src/main/native/systemcore/HAL.cpp +++ b/hal/src/main/native/systemcore/HAL.cpp @@ -60,7 +60,6 @@ void InitializeHAL() { InitializeEncoder(); InitializeFRCDriverStation(); InitializeI2C(); - InitializeInterrupts(); InitializeLEDs(); InitializeMain(); InitializeNotifier(); diff --git a/hal/src/main/native/systemcore/HALInitializer.h b/hal/src/main/native/systemcore/HALInitializer.h index e4c2d3e83d9..913743402ae 100644 --- a/hal/src/main/native/systemcore/HALInitializer.h +++ b/hal/src/main/native/systemcore/HALInitializer.h @@ -30,11 +30,9 @@ extern void InitializeDigitalInternal(); extern void InitializeDIO(); extern void InitializeDutyCycle(); extern void InitializeEncoder(); -extern void InitializeFPGAEncoder(); extern void InitializeFRCDriverStation(); extern void InitializeHAL(); extern void InitializeI2C(); -extern void InitializeInterrupts(); extern void InitializeLEDs(); extern void InitializeMain(); extern void InitializeNotifier(); diff --git a/hal/src/main/native/systemcore/Interrupts.cpp b/hal/src/main/native/systemcore/Interrupts.cpp deleted file mode 100644 index c7bff65f8fd..00000000000 --- a/hal/src/main/native/systemcore/Interrupts.cpp +++ /dev/null @@ -1,83 +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. - -#include "hal/Interrupts.h" - -#include - -#include - -#include "HALInitializer.h" -#include "HALInternal.h" -#include "PortsInternal.h" -#include "hal/Errors.h" -#include "hal/HALBase.h" -#include "hal/handles/HandlesInternal.h" -#include "hal/handles/LimitedHandleResource.h" - -using namespace hal; - -namespace hal::init { -void InitializeInterrupts() {} -} // namespace hal::init - -extern "C" { - -HAL_InterruptHandle HAL_InitializeInterrupts(int32_t* status) { - hal::init::CheckInit(); - *status = HAL_HANDLE_ERROR; - return HAL_kInvalidHandle; -} - -void HAL_CleanInterrupts(HAL_InterruptHandle interruptHandle) {} - -int64_t HAL_WaitForInterrupt(HAL_InterruptHandle interruptHandle, - double timeout, HAL_Bool ignorePrevious, - int32_t* status) { - *status = HAL_HANDLE_ERROR; - return 0; -} - -int64_t HAL_WaitForMultipleInterrupts(HAL_InterruptHandle interruptHandle, - int64_t mask, double timeout, - HAL_Bool ignorePrevious, - int32_t* status) { - *status = HAL_HANDLE_ERROR; - return 0; -} - -int64_t HAL_ReadInterruptRisingTimestamp(HAL_InterruptHandle interruptHandle, - int32_t* status) { - *status = HAL_HANDLE_ERROR; - return 0; -} - -int64_t HAL_ReadInterruptFallingTimestamp(HAL_InterruptHandle interruptHandle, - int32_t* status) { - *status = HAL_HANDLE_ERROR; - return 0; -} - -void HAL_RequestInterrupts(HAL_InterruptHandle interruptHandle, - HAL_Handle digitalSourceHandle, - HAL_AnalogTriggerType analogTriggerType, - int32_t* status) { - *status = HAL_HANDLE_ERROR; - return; -} - -void HAL_SetInterruptUpSourceEdge(HAL_InterruptHandle interruptHandle, - HAL_Bool risingEdge, HAL_Bool fallingEdge, - int32_t* status) { - *status = HAL_HANDLE_ERROR; - return; -} - -void HAL_ReleaseWaitingInterrupt(HAL_InterruptHandle interruptHandle, - int32_t* status) { - *status = HAL_HANDLE_ERROR; - return; -} - -} // extern "C" diff --git a/wpilibc/src/main/native/cpp/AsynchronousInterrupt.cpp b/wpilibc/src/main/native/cpp/AsynchronousInterrupt.cpp deleted file mode 100644 index 20fc761c278..00000000000 --- a/wpilibc/src/main/native/cpp/AsynchronousInterrupt.cpp +++ /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. - -#include "frc/AsynchronousInterrupt.h" - -#include - -#include -#include - -using namespace frc; - -AsynchronousInterrupt::AsynchronousInterrupt( - DigitalSource& source, std::function callback) - : m_interrupt{source}, m_callback{std::move(callback)} {} -AsynchronousInterrupt::AsynchronousInterrupt( - DigitalSource* source, std::function callback) - : m_interrupt{source}, m_callback{std::move(callback)} {} -AsynchronousInterrupt::AsynchronousInterrupt( - std::shared_ptr source, - std::function callback) - : m_interrupt{source}, m_callback{std::move(callback)} {} - -AsynchronousInterrupt::~AsynchronousInterrupt() { - Disable(); -} - -void AsynchronousInterrupt::ThreadMain() { - while (m_keepRunning) { - auto result = m_interrupt.WaitForInterrupt(10_s, false); - if (!m_keepRunning) { - break; - } - if (result == SynchronousInterrupt::WaitResult::kTimeout) { - continue; - } - m_callback((result & SynchronousInterrupt::WaitResult::kRisingEdge) != 0, - (result & SynchronousInterrupt::WaitResult::kFallingEdge) != 0); - } -} - -void AsynchronousInterrupt::Enable() { - if (m_keepRunning) { - return; - } - - m_keepRunning = true; - m_thread = std::thread([this] { this->ThreadMain(); }); -} - -void AsynchronousInterrupt::Disable() { - m_keepRunning = false; - m_interrupt.WakeupWaitingInterrupt(); - if (m_thread.joinable()) { - m_thread.join(); - } -} - -void AsynchronousInterrupt::SetInterruptEdges(bool risingEdge, - bool fallingEdge) { - m_interrupt.SetInterruptEdges(risingEdge, fallingEdge); -} - -units::second_t AsynchronousInterrupt::GetRisingTimestamp() { - return m_interrupt.GetRisingTimestamp(); -} -units::second_t AsynchronousInterrupt::GetFallingTimestamp() { - return m_interrupt.GetFallingTimestamp(); -} diff --git a/wpilibc/src/main/native/cpp/SynchronousInterrupt.cpp b/wpilibc/src/main/native/cpp/SynchronousInterrupt.cpp deleted file mode 100644 index 084efd9d1f1..00000000000 --- a/wpilibc/src/main/native/cpp/SynchronousInterrupt.cpp +++ /dev/null @@ -1,103 +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. - -#include "frc/SynchronousInterrupt.h" - -#include -#include -#include - -#include -#include - -#include "frc/DigitalSource.h" -#include "frc/Errors.h" - -using namespace frc; - -SynchronousInterrupt::SynchronousInterrupt(DigitalSource& source) - : m_source{&source, wpi::NullDeleter()} { - InitSynchronousInterrupt(); -} -SynchronousInterrupt::SynchronousInterrupt(DigitalSource* source) - : m_source{source, wpi::NullDeleter()} { - if (m_source == nullptr) { - FRC_CheckErrorStatus(frc::err::NullParameter, "Source is null"); - } else { - InitSynchronousInterrupt(); - } -} -SynchronousInterrupt::SynchronousInterrupt( - std::shared_ptr source) - : m_source{std::move(source)} { - if (m_source == nullptr) { - FRC_CheckErrorStatus(frc::err::NullParameter, "Source is null"); - } else { - InitSynchronousInterrupt(); - } -} - -void SynchronousInterrupt::InitSynchronousInterrupt() { - int32_t status = 0; - m_handle = HAL_InitializeInterrupts(&status); - FRC_CheckErrorStatus(status, "Interrupt failed to initialize"); - HAL_RequestInterrupts(m_handle, m_source->GetPortHandleForRouting(), - static_cast( - m_source->GetAnalogTriggerTypeForRouting()), - &status); - FRC_CheckErrorStatus(status, "Interrupt request failed"); - HAL_SetInterruptUpSourceEdge(m_handle, true, false, &status); - FRC_CheckErrorStatus(status, "Interrupt setting up source edge failed"); -} - -inline SynchronousInterrupt::WaitResult operator|( - SynchronousInterrupt::WaitResult lhs, - SynchronousInterrupt::WaitResult rhs) { - using T = std::underlying_type_t; - return static_cast(static_cast(lhs) | - static_cast(rhs)); -} - -SynchronousInterrupt::WaitResult SynchronousInterrupt::WaitForInterrupt( - units::second_t timeout, bool ignorePrevious) { - int32_t status = 0; - auto result = - HAL_WaitForInterrupt(m_handle, timeout.value(), ignorePrevious, &status); - - auto rising = - ((result & 0xFF) != 0) ? WaitResult::kRisingEdge : WaitResult::kTimeout; - auto falling = ((result & 0xFF00) != 0) ? WaitResult::kFallingEdge - : WaitResult::kTimeout; - - return rising | falling; -} - -void SynchronousInterrupt::SetInterruptEdges(bool risingEdge, - bool fallingEdge) { - int32_t status = 0; - HAL_SetInterruptUpSourceEdge(m_handle, risingEdge, fallingEdge, &status); - FRC_CheckErrorStatus(status, "Interrupt setting edges failed"); -} - -void SynchronousInterrupt::WakeupWaitingInterrupt() { - int32_t status = 0; - HAL_ReleaseWaitingInterrupt(m_handle, &status); - FRC_CheckErrorStatus(status, "Interrupt wakeup failed"); -} - -units::second_t SynchronousInterrupt::GetRisingTimestamp() { - int32_t status = 0; - auto ts = HAL_ReadInterruptRisingTimestamp(m_handle, &status); - FRC_CheckErrorStatus(status, "Interrupt rising timestamp failed"); - units::microsecond_t ms{static_cast(ts)}; - return ms; -} - -units::second_t SynchronousInterrupt::GetFallingTimestamp() { - int32_t status = 0; - auto ts = HAL_ReadInterruptFallingTimestamp(m_handle, &status); - FRC_CheckErrorStatus(status, "Interrupt falling timestamp failed"); - units::microsecond_t ms{static_cast(ts)}; - return ms; -} diff --git a/wpilibc/src/main/native/include/frc/AsynchronousInterrupt.h b/wpilibc/src/main/native/include/frc/AsynchronousInterrupt.h deleted file mode 100644 index 0dea5bc8e73..00000000000 --- a/wpilibc/src/main/native/include/frc/AsynchronousInterrupt.h +++ /dev/null @@ -1,180 +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 - -namespace frc { -/** - * Class for handling asynchronous interrupts using a callback thread. - * - *

By default, interrupts will occur on rising edge. Callbacks are disabled - * by default, and Enable() must be called before they will occur. - * - *

Both rising and falling edges can be indicated in one callback if both a - * rising and falling edge occurred since the previous callback. - * - *

Synchronous (blocking) interrupts are handled by the SynchronousInterrupt - * class. - */ -class AsynchronousInterrupt { - public: - /** - * Construct an Asynchronous Interrupt from a Digital Source. - * - *

At construction, the interrupt will trigger on the rising edge. - * - *

The first bool in the callback indicates the rising edge triggered the - * interrupt, the second bool is falling edge. - * - * @param source the DigitalSource the interrupts are triggered from - * @param callback the callback function to call when the interrupt is - * triggered - */ - AsynchronousInterrupt(DigitalSource& source, - std::function callback); - - /** - * Construct an Asynchronous Interrupt from a Digital Source. - * - *

At construction, the interrupt will trigger on the rising edge. - * - *

The first bool in the callback indicates the rising edge triggered the - * interrupt, the second bool is falling edge. - * - * @param source the DigitalSource the interrupts are triggered from - * @param callback the callback function to call when the interrupt is - * triggered - */ - AsynchronousInterrupt(DigitalSource* source, - std::function callback); - - /** - * Construct an Asynchronous Interrupt from a Digital Source. - * - *

At construction, the interrupt will trigger on the rising edge. - * - *

The first bool in the callback indicates the rising edge triggered the - * interrupt, the second bool is falling edge. - * - * @param source the DigitalSource the interrupts are triggered from - * @param callback the callback function to call when the interrupt is - * triggered - */ - AsynchronousInterrupt(std::shared_ptr source, - std::function callback); - - /** - * Construct an Asynchronous Interrupt from a Digital Source. - * - *

At construction, the interrupt will trigger on the rising edge. - * - * @param source the DigitalSource the interrupts are triggered from - * @param f the callback function to call when the interrupt is triggered - * @param arg the first argument, interrupt was triggered on rising edge - * @param args the remaining arguments, interrupt was triggered on falling - * edge - */ - template - AsynchronousInterrupt(DigitalSource& source, Callable&& f, Arg&& arg, - Args&&... args) - : AsynchronousInterrupt( - source, std::bind(std::forward(f), std::forward(arg), - std::forward(args)...)) {} - - /** - * Construct an Asynchronous Interrupt from a Digital Source. - * - *

At construction, the interrupt will trigger on the rising edge. - * - * @param source the DigitalSource the interrupts are triggered from - * @param f the callback function to call when the interrupt is triggered - * @param arg the first argument, interrupt was triggered on rising edge - * @param args the remaining arguments, interrupt was triggered on falling - * edge - */ - template - AsynchronousInterrupt(DigitalSource* source, Callable&& f, Arg&& arg, - Args&&... args) - : AsynchronousInterrupt( - source, std::bind(std::forward(f), std::forward(arg), - std::forward(args)...)) {} - - /** - * Construct an Asynchronous Interrupt from a Digital Source. - * - *

At construction, the interrupt will trigger on the rising edge. - * - * @param source the DigitalSource the interrupts are triggered from - * @param f the callback function to call when the interrupt is triggered - * @param arg the first argument, interrupt was triggered on rising edge - * @param args the remaining arguments, interrupt was triggered on falling - * edge - */ - template - AsynchronousInterrupt(std::shared_ptr source, Callable&& f, - Arg&& arg, Args&&... args) - : AsynchronousInterrupt( - source, std::bind(std::forward(f), std::forward(arg), - std::forward(args)...)) {} - - ~AsynchronousInterrupt(); - - /** - * Enables interrupt callbacks. Before this, callbacks will not occur. Does - * nothing if already enabled. - */ - void Enable(); - - /** - * Disables interrupt callbacks. Does nothing if already disabled. - */ - void Disable(); - - /** - * Set which edges to trigger the interrupt on. - * - * @param risingEdge %Trigger on rising edge - * @param fallingEdge %Trigger on falling edge - */ - void SetInterruptEdges(bool risingEdge, bool fallingEdge); - - /** - * Get the timestamp of the last rising edge. - * - *

This function does not require the interrupt to be enabled to work. - * - *

This only works if rising edge was configured using SetInterruptEdges. - * @return the timestamp in seconds relative to GetFPGATime - */ - units::second_t GetRisingTimestamp(); - - /** - * Get the timestamp of the last falling edge. - * - *

This function does not require the interrupt to be enabled to work. - * - *

This only works if falling edge was configured using SetInterruptEdges. - * @return the timestamp in seconds relative to GetFPGATime - */ - units::second_t GetFallingTimestamp(); - - private: - void ThreadMain(); - - std::atomic_bool m_keepRunning{false}; - std::thread m_thread; - SynchronousInterrupt m_interrupt; - std::function m_callback; -}; -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/SynchronousInterrupt.h b/wpilibc/src/main/native/include/frc/SynchronousInterrupt.h deleted file mode 100644 index 15ce7fb6cdd..00000000000 --- a/wpilibc/src/main/native/include/frc/SynchronousInterrupt.h +++ /dev/null @@ -1,112 +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 - -namespace frc { -class DigitalSource; - -/** - * Class for handling synchronous (blocking) interrupts. - * - *

By default, interrupts will occur on rising edge. - * - *

Asynchronous interrupts are handled by the AsynchronousInterrupt class. - */ -class SynchronousInterrupt { - public: - /** - * Event trigger combinations for a synchronous interrupt. - */ - enum WaitResult { - /// Timeout event. - kTimeout = 0x0, - /// Rising edge event. - kRisingEdge = 0x1, - /// Falling edge event. - kFallingEdge = 0x100, - /// Both rising and falling edge events. - kBoth = 0x101, - }; - - /** - * Construct a Synchronous Interrupt from a Digital Source. - * - * @param source the DigitalSource the interrupts are triggered from - */ - explicit SynchronousInterrupt(DigitalSource& source); - - /** - * Construct a Synchronous Interrupt from a Digital Source. - * - * @param source the DigitalSource the interrupts are triggered from - */ - explicit SynchronousInterrupt(DigitalSource* source); - - /** - * Construct a Synchronous Interrupt from a Digital Source. - * - * @param source the DigitalSource the interrupts are triggered from - */ - explicit SynchronousInterrupt(std::shared_ptr source); - - SynchronousInterrupt(SynchronousInterrupt&&) = default; - SynchronousInterrupt& operator=(SynchronousInterrupt&&) = default; - - /** - * Wait for an interrupt to occur. - * - *

Both rising and falling edge can be returned if both a rising and - * falling happened between calls, and ignorePrevious is false. - * - * @param timeout The timeout to wait for. 0s or less will return immediately. - * @param ignorePrevious True to ignore any previous interrupts, false to - * return interrupt value if an interrupt has occurred since last call. - * @return The edge(s) that were triggered, or timeout. - */ - WaitResult WaitForInterrupt(units::second_t timeout, - bool ignorePrevious = true); - - /** - * Set which edges cause an interrupt to occur. - * - * @param risingEdge true to trigger on rising edge, false otherwise. - * @param fallingEdge true to trigger on falling edge, false otherwise - */ - void SetInterruptEdges(bool risingEdge, bool fallingEdge); - - /** - * Get the timestamp (relative to FPGA Time) of the last rising edge. - * - * @return the timestamp in seconds relative to getFPGATime - */ - units::second_t GetRisingTimestamp(); - - /** - * Get the timestamp of the last falling edge. - * - *

This function does not require the interrupt to be enabled to work. - * - *

This only works if falling edge was configured using setInterruptEdges. - * @return the timestamp in seconds relative to getFPGATime - */ - units::second_t GetFallingTimestamp(); - - /** - * Wake up an existing wait call. Can be called from any thread. - */ - void WakeupWaitingInterrupt(); - - private: - void InitSynchronousInterrupt(); - std::shared_ptr m_source; - hal::Handle m_handle; -}; -} // namespace frc diff --git a/wpilibc/src/test/native/cpp/InterruptTest.cpp b/wpilibc/src/test/native/cpp/InterruptTest.cpp deleted file mode 100644 index 8b054d75f59..00000000000 --- a/wpilibc/src/test/native/cpp/InterruptTest.cpp +++ /dev/null @@ -1,103 +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. - -#include - -#include -#include - -#include "frc/AsynchronousInterrupt.h" -#include "frc/DigitalInput.h" -#include "frc/Timer.h" -#include "frc/simulation/DIOSim.h" - -namespace frc { -using namespace frc::sim; -TEST(InterruptTest, AsynchronousInterrupt) { - HAL_Initialize(500, 0); - - std::atomic_int counter{0}; - std::atomic_bool hasFired{false}; - - DigitalInput di{0}; - AsynchronousInterrupt interrupt{di, [&](bool rising, bool falling) { - counter++; - hasFired = true; - }}; - - interrupt.Enable(); - frc::Wait(0.5_s); - DIOSim digitalSim{di}; - digitalSim.SetValue(false); - frc::Wait(20_ms); - digitalSim.SetValue(true); - frc::Wait(20_ms); - - int count = 0; - while (!hasFired) { - frc::Wait(5_ms); - count++; - ASSERT_TRUE(count < 1000); - } - ASSERT_EQ(1, counter.load()); -} - -TEST(InterruptTest, RisingEdge) { - HAL_Initialize(500, 0); - - std::atomic_bool hasFiredFallingEdge{false}; - std::atomic_bool hasFiredRisingEdge{false}; - - DigitalInput di{0}; - AsynchronousInterrupt interrupt{di, [&](bool rising, bool falling) { - hasFiredFallingEdge = falling; - hasFiredRisingEdge = rising; - }}; - interrupt.SetInterruptEdges(true, true); - DIOSim digitalSim{di}; - digitalSim.SetValue(false); - interrupt.Enable(); - frc::Wait(0.5_s); - digitalSim.SetValue(true); - frc::Wait(20_ms); - - int count = 0; - while (!hasFiredRisingEdge) { - frc::Wait(5_ms); - count++; - ASSERT_TRUE(count < 1000); - } - EXPECT_FALSE(hasFiredFallingEdge); - EXPECT_TRUE(hasFiredRisingEdge); -} - -TEST(InterruptTest, FallingEdge) { - HAL_Initialize(500, 0); - - std::atomic_bool hasFiredFallingEdge{false}; - std::atomic_bool hasFiredRisingEdge{false}; - - DigitalInput di{0}; - AsynchronousInterrupt interrupt{di, [&](bool rising, bool falling) { - hasFiredFallingEdge = falling; - hasFiredRisingEdge = rising; - }}; - interrupt.SetInterruptEdges(true, true); - DIOSim digitalSim{di}; - digitalSim.SetValue(true); - interrupt.Enable(); - frc::Wait(0.5_s); - digitalSim.SetValue(false); - frc::Wait(20_ms); - - int count = 0; - while (!hasFiredFallingEdge) { - frc::Wait(5_ms); - count++; - ASSERT_TRUE(count < 1000); - } - EXPECT_TRUE(hasFiredFallingEdge); - EXPECT_FALSE(hasFiredRisingEdge); -} -} // namespace frc diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AsynchronousInterrupt.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AsynchronousInterrupt.java deleted file mode 100644 index f64284f61a6..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AsynchronousInterrupt.java +++ /dev/null @@ -1,155 +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. - -package edu.wpi.first.wpilibj; - -import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.BiConsumer; - -/** - * Class for handling asynchronous interrupts using a callback thread. - * - *

By default, interrupts will occur on rising edge. Callbacks are disabled by default, and - * enable() must be called before they will occur. - * - *

Both rising and falling edges can be indicated in one callback if both a rising and falling - * edge occurred since the previous callback. - * - *

Synchronous (blocking) interrupts are handled by the SynchronousInterrupt class. - */ -public class AsynchronousInterrupt implements AutoCloseable { - private final BiConsumer m_callback; - private final SynchronousInterrupt m_interrupt; - - private final AtomicBoolean m_keepRunning = new AtomicBoolean(false); - private Thread m_thread; - - /** - * Construct a new asynchronous interrupt using a Digital Source. - * - *

At construction, the interrupt will trigger on the rising edge. - * - *

Callbacks will not be triggered until enable() is called. - * - *

The first bool in the callback indicates the rising edge triggered the interrupt, the second - * bool is falling edge. - * - * @param source The digital source to use. - * @param callback The callback to call on an interrupt - */ - public AsynchronousInterrupt(DigitalSource source, BiConsumer callback) { - m_callback = requireNonNullParam(callback, "callback", "AsynchronousInterrupt"); - m_interrupt = new SynchronousInterrupt(source); - } - - /** - * Closes the interrupt. - * - *

This does not close the associated digital source. - * - *

This will disable the interrupt if it is enabled. - */ - @Override - public void close() { - disable(); - m_interrupt.close(); - } - - /** - * Enables interrupt callbacks. Before this, callbacks will not occur. Does nothing if already - * enabled. - */ - public void enable() { - if (m_keepRunning.get()) { - return; - } - - m_keepRunning.set(true); - m_thread = new Thread(this::threadMain); - m_thread.start(); - } - - /** Disables interrupt callbacks. Does nothing if already disabled. */ - public void disable() { - m_keepRunning.set(false); - m_interrupt.wakeupWaitingInterrupt(); - if (m_thread != null) { - if (m_thread.isAlive()) { - try { - m_thread.interrupt(); - m_thread.join(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - m_thread = null; - } - } - - /** - * Set which edges to trigger the interrupt on. - * - * @param risingEdge Trigger on rising edge - * @param fallingEdge Trigger on falling edge - */ - public void setInterruptEdges(boolean risingEdge, boolean fallingEdge) { - m_interrupt.setInterruptEdges(risingEdge, fallingEdge); - } - - /** - * Get the timestamp of the last rising edge. - * - *

This function does not require the interrupt to be enabled to work. - * - *

This only works if rising edge was configured using setInterruptEdges. - * - * @return the timestamp in seconds relative to getFPGATime - */ - public double getRisingTimestamp() { - return m_interrupt.getRisingTimestamp(); - } - - /** - * Get the timestamp of the last falling edge. - * - *

This function does not require the interrupt to be enabled to work. - * - *

This only works if falling edge was configured using setInterruptEdges. - * - * @return the timestamp in seconds relative to getFPGATime - */ - public double getFallingTimestamp() { - return m_interrupt.getFallingTimestamp(); - } - - private void threadMain() { - while (m_keepRunning.get()) { - var result = m_interrupt.waitForInterrupt(10, false); - if (!m_keepRunning.get()) { - break; - } - boolean rising = false; - boolean falling = false; - switch (result) { - case kBoth -> { - rising = true; - falling = true; - } - case kFallingEdge -> { - falling = true; - } - case kRisingEdge -> { - rising = true; - } - default -> { - continue; - } - } - - m_callback.accept(rising, falling); - } - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/SynchronousInterrupt.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/SynchronousInterrupt.java deleted file mode 100644 index 449402c6cdf..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/SynchronousInterrupt.java +++ /dev/null @@ -1,154 +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. - -package edu.wpi.first.wpilibj; - -import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; - -import edu.wpi.first.hal.InterruptJNI; - -/** - * Class for handling synchronous (blocking) interrupts. - * - *

By default, interrupts will occur on rising edge. - * - *

Asynchronous interrupts are handled by the AsynchronousInterrupt class. - */ -public class SynchronousInterrupt implements AutoCloseable { - @SuppressWarnings("PMD.SingularField") - private final DigitalSource m_source; - - private final int m_handle; - - /** Event trigger combinations for a synchronous interrupt. */ - public enum WaitResult { - /** Timeout event. */ - kTimeout(0x0), - /** Rising edge event. */ - kRisingEdge(0x1), - /** Falling edge event. */ - kFallingEdge(0x100), - /** Both rising and falling edge events. */ - kBoth(0x101); - - /** WaitResult value. */ - public final int value; - - WaitResult(int value) { - this.value = value; - } - - /** - * Create a wait result enum. - * - * @param rising True if a rising edge occurred. - * @param falling True if a falling edge occurred. - * @return A wait result enum. - */ - public static WaitResult getValue(boolean rising, boolean falling) { - if (rising && falling) { - return kBoth; - } else if (rising) { - return kRisingEdge; - } else if (falling) { - return kFallingEdge; - } else { - return kTimeout; - } - } - } - - /** - * Constructs a new synchronous interrupt using a DigitalSource. - * - *

At construction, the interrupt will trigger on the rising edge. - * - * @param source The digital source to use. - */ - public SynchronousInterrupt(DigitalSource source) { - m_source = requireNonNullParam(source, "source", "SynchronousInterrupt"); - m_handle = InterruptJNI.initializeInterrupts(); - InterruptJNI.requestInterrupts( - m_handle, m_source.getPortHandleForRouting(), m_source.getAnalogTriggerTypeForRouting()); - InterruptJNI.setInterruptUpSourceEdge(m_handle, true, false); - } - - /** - * Closes the interrupt. - * - *

This does not close the associated digital source. - */ - @Override - public void close() { - InterruptJNI.cleanInterrupts(m_handle); - } - - /** - * Wait for an interrupt. - * - * @param timeoutSeconds The timeout in seconds. 0 or less will return immediately. - * @param ignorePrevious True to ignore if a previous interrupt has occurred, and only wait for a - * new trigger. False will consider if an interrupt has occurred since the last time the - * interrupt was read. - * @return Result of which edges were triggered, or if a timeout occurred. - */ - public WaitResult waitForInterrupt(double timeoutSeconds, boolean ignorePrevious) { - long result = InterruptJNI.waitForInterrupt(m_handle, timeoutSeconds, ignorePrevious); - - // Rising edge result is the interrupt bit set in the byte 0xFF - // Falling edge result is the interrupt bit set in the byte 0xFF00 - // Set any bit set to be true for that edge, and then conduct a logical AND on the 2 results - // together to match the existing enum for all interrupts - boolean rising = (result & 0xFF) != 0; - boolean falling = (result & 0xFF00) != 0; - return WaitResult.getValue(rising, falling); - } - - /** - * Wait for an interrupt, ignoring any previously occurring interrupts. - * - * @param timeoutSeconds The timeout in seconds. 0 or less will return immediately. - * @return Result of which edges were triggered, or if a timeout occurred. - */ - public WaitResult waitForInterrupt(double timeoutSeconds) { - return waitForInterrupt(timeoutSeconds, true); - } - - /** - * Set which edges to trigger the interrupt on. - * - * @param risingEdge Trigger on rising edge - * @param fallingEdge Trigger on falling edge - */ - public void setInterruptEdges(boolean risingEdge, boolean fallingEdge) { - InterruptJNI.setInterruptUpSourceEdge(m_handle, risingEdge, fallingEdge); - } - - /** - * Get the timestamp of the last rising edge. - * - *

This only works if rising edge was configured using setInterruptEdges. - * - * @return the timestamp in seconds relative to getFPGATime - */ - public double getRisingTimestamp() { - return InterruptJNI.readInterruptRisingTimestamp(m_handle) * 1e-6; - } - - /** - * Get the timestamp of the last falling edge. - * - *

This only works if falling edge was configured using setInterruptEdges. - * - * @return the timestamp in seconds relative to getFPGATime - */ - public double getFallingTimestamp() { - return InterruptJNI.readInterruptFallingTimestamp(m_handle) * 1e-6; - } - - /** Force triggering of any waiting interrupt, which will be seen as a timeout. */ - public void wakeupWaitingInterrupt() { - InterruptJNI.releaseWaitingInterrupt(m_handle); - } -} diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/InterruptTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/InterruptTest.java deleted file mode 100644 index 7855d89753e..00000000000 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/InterruptTest.java +++ /dev/null @@ -1,120 +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. - -package edu.wpi.first.wpilibj; - -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import edu.wpi.first.wpilibj.simulation.DIOSim; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import org.junit.jupiter.api.Test; - -class InterruptTest { - @Test - void testAsynchronousInterrupt() { - AtomicBoolean hasFired = new AtomicBoolean(false); - AtomicInteger counter = new AtomicInteger(0); - - try (DigitalInput di = new DigitalInput(0); - AsynchronousInterrupt interrupt = - new AsynchronousInterrupt( - di, - (rising, falling) -> { - counter.incrementAndGet(); - hasFired.set(true); - })) { - interrupt.enable(); - Timer.delay(0.5); - DIOSim digitalSim = new DIOSim(di); - digitalSim.setValue(false); - Timer.delay(0.02); - digitalSim.setValue(true); - Timer.delay(0.02); - - int count = 0; - while (!hasFired.get()) { - Timer.delay(0.005); - count++; - assertTrue(count < 1000); - } - assertEquals(1, counter.get(), "The interrupt did not fire the expected number of times"); - } - } - - @Test - void testRisingEdge() { - AtomicBoolean hasFiredFallingEdge = new AtomicBoolean(false); - AtomicBoolean hasFiredRisingEdge = new AtomicBoolean(false); - - try (DigitalInput di = new DigitalInput(0); - AsynchronousInterrupt interrupt = - new AsynchronousInterrupt( - di, - (rising, falling) -> { - hasFiredFallingEdge.set(falling); - hasFiredRisingEdge.set(rising); - })) { - interrupt.setInterruptEdges(true, true); - DIOSim digitalSim = new DIOSim(di); - digitalSim.setValue(false); - interrupt.enable(); - Timer.delay(0.5); - digitalSim.setValue(true); - Timer.delay(0.02); - - int count = 0; - while (!hasFiredRisingEdge.get()) { - Timer.delay(0.005); - count++; - assertTrue(count < 1000); - } - assertAll( - () -> - assertFalse(hasFiredFallingEdge.get(), "The interrupt triggered on the falling edge"), - () -> - assertTrue( - hasFiredRisingEdge.get(), "The interrupt did not trigger on the rising edge")); - } - } - - @Test - void testFallingEdge() { - AtomicBoolean hasFiredFallingEdge = new AtomicBoolean(false); - AtomicBoolean hasFiredRisingEdge = new AtomicBoolean(false); - - try (DigitalInput di = new DigitalInput(0); - AsynchronousInterrupt interrupt = - new AsynchronousInterrupt( - di, - (rising, falling) -> { - hasFiredFallingEdge.set(falling); - hasFiredRisingEdge.set(rising); - })) { - interrupt.setInterruptEdges(true, true); - DIOSim digitalSim = new DIOSim(di); - digitalSim.setValue(true); - interrupt.enable(); - Timer.delay(0.5); - digitalSim.setValue(false); - Timer.delay(0.02); - - int count = 0; - while (!hasFiredFallingEdge.get()) { - Timer.delay(0.005); - count++; - assertTrue(count < 1000); - } - assertAll( - () -> - assertTrue( - hasFiredFallingEdge.get(), "The interrupt did not trigger on the rising edge"), - () -> - assertFalse(hasFiredRisingEdge.get(), "The interrupt triggered on the rising edge")); - } - } -} From 01e71e73ce67d126d4e9152c064e85481f165d25 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Fri, 24 Jan 2025 23:47:09 -0800 Subject: [PATCH 3/6] [build] developerRobot: Fix link order (#7732) ntcore now needs to be after hal. --- developerRobot/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/developerRobot/build.gradle b/developerRobot/build.gradle index ca404e82ffc..bf711d96679 100644 --- a/developerRobot/build.gradle +++ b/developerRobot/build.gradle @@ -202,8 +202,6 @@ model { lib project: ':wpilibc', library: 'wpilibc', linkage: 'shared' lib project: ':wpimath', library: 'wpimath', linkage: 'shared' lib project: ':cameraserver', library: 'cameraserver', linkage: 'shared' - project(':ntcore').addNtcoreDependency(binary, 'shared') - project(':ntcore').addNtcoreJniDependency(binary) lib project: ':cscore', library: 'cscore', linkage: 'shared' lib project: ':cscore', library: 'cscoreJNIShared', linkage: 'shared' lib project: ':wpimath', library: 'wpimathJNIShared', linkage: 'shared' @@ -211,6 +209,8 @@ model { lib project: ':wpiutil', library: 'wpiutilJNIShared', linkage: 'shared' project(':hal').addHalDependency(binary, 'shared') project(':hal').addHalJniDependency(binary) + project(':ntcore').addNtcoreDependency(binary, 'shared') + project(':ntcore').addNtcoreJniDependency(binary) lib project: ':wpinet', library: 'wpinet', linkage: 'shared' lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared' def systemArch = getCurrentArch() @@ -247,9 +247,9 @@ model { lib project: ':wpilibc', library: 'wpilibc', linkage: 'static' lib project: ':wpimath', library: 'wpimath', linkage: 'static' lib project: ':cameraserver', library: 'cameraserver', linkage: 'static' - project(':ntcore').addNtcoreDependency(binary, 'static') lib project: ':cscore', library: 'cscore', linkage: 'static' project(':hal').addHalDependency(binary, 'static') + project(':ntcore').addNtcoreDependency(binary, 'static') lib project: ':wpinet', library: 'wpinet', linkage: 'static' lib project: ':wpiutil', library: 'wpiutil', linkage: 'static' } From adbe95e610012f8b6b4243b2c9ed9f194e681c5c Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Fri, 24 Jan 2025 23:47:42 -0800 Subject: [PATCH 4/6] [wpilib] Remove Shuffleboard API (#7730) --- .../main/native/cpp/IterativeRobotBase.cpp | 5 - .../native/cpp/shuffleboard/ComplexWidget.cpp | 46 -- .../native/cpp/shuffleboard/LayoutType.cpp | 11 - .../cpp/shuffleboard/RecordingController.cpp | 50 -- .../shuffleboard/SendableCameraWrapper.cpp | 32 - .../native/cpp/shuffleboard/Shuffleboard.cpp | 92 --- .../ShuffleboardComponentBase.cpp | 66 -- .../shuffleboard/ShuffleboardContainer.cpp | 404 ---------- .../cpp/shuffleboard/ShuffleboardInstance.cpp | 94 --- .../cpp/shuffleboard/ShuffleboardLayout.cpp | 35 - .../cpp/shuffleboard/ShuffleboardTab.cpp | 32 - .../cpp/shuffleboard/ShuffleboardWidget.cpp | 39 - .../native/cpp/shuffleboard/SimpleWidget.cpp | 51 -- .../native/cpp/shuffleboard/WidgetType.cpp | 11 - .../include/frc/shuffleboard/BuiltInLayouts.h | 49 -- .../include/frc/shuffleboard/BuiltInWidgets.h | 385 ---------- .../include/frc/shuffleboard/ComplexWidget.h | 46 -- .../include/frc/shuffleboard/LayoutType.h | 34 - .../frc/shuffleboard/RecordingController.h | 40 - .../frc/shuffleboard/SendableCameraWrapper.h | 136 ---- .../include/frc/shuffleboard/Shuffleboard.h | 196 ----- .../frc/shuffleboard/ShuffleboardComponent.h | 89 --- .../shuffleboard/ShuffleboardComponentBase.h | 55 -- .../frc/shuffleboard/ShuffleboardContainer.h | 727 ------------------ .../ShuffleboardEventImportance.h | 40 - .../frc/shuffleboard/ShuffleboardInstance.h | 40 - .../frc/shuffleboard/ShuffleboardLayout.h | 40 - .../frc/shuffleboard/ShuffleboardRoot.h | 63 -- .../frc/shuffleboard/ShuffleboardTab.h | 39 - .../frc/shuffleboard/ShuffleboardValue.h | 67 -- .../frc/shuffleboard/ShuffleboardWidget.h | 74 -- .../include/frc/shuffleboard/SimpleWidget.h | 54 -- .../frc/shuffleboard/SuppliedValueWidget.h | 58 -- .../include/frc/shuffleboard/WidgetType.h | 34 - .../cpp/shuffleboard/MockActuatorSendable.cpp | 16 - .../shuffleboard/ShuffleboardInstanceTest.cpp | 130 ---- .../cpp/shuffleboard/ShuffleboardTest.cpp | 13 - .../shuffleboard/SuppliedValueWidgetTest.cpp | 110 --- .../shuffleboard/MockActuatorSendable.h | 19 - .../HatchbotInlined/cpp/RobotContainer.cpp | 34 +- .../cpp/RobotContainer.cpp | 34 +- .../cpp/RobotContainer.cpp | 1 - .../cpp/examples/ShuffleBoard/cpp/Robot.cpp | 88 --- .../main/cpp/examples/Solenoid/cpp/Robot.cpp | 50 +- .../cpp/RobotContainer.cpp | 1 - .../cpp/examples/Ultrasonic/cpp/Robot.cpp | 3 +- .../src/main/cpp/examples/examples.json | 21 +- .../templates/robotbaseskeleton/cpp/Robot.cpp | 3 - .../wpi/first/wpilibj/IterativeRobotBase.java | 5 - .../java/edu/wpi/first/wpilibj/RobotBase.java | 2 - .../wpilibj/shuffleboard/BuiltInLayouts.java | 61 -- .../wpilibj/shuffleboard/BuiltInWidgets.java | 476 ------------ .../wpilibj/shuffleboard/ComplexWidget.java | 57 -- .../wpilibj/shuffleboard/ContainerHelper.java | 190 ----- .../wpilibj/shuffleboard/EventImportance.java | 49 -- .../wpilibj/shuffleboard/LayoutType.java | 20 - .../shuffleboard/RecordingController.java | 65 -- .../shuffleboard/SendableCameraWrapper.java | 138 ---- .../wpilibj/shuffleboard/Shuffleboard.java | 195 ----- .../shuffleboard/ShuffleboardComponent.java | 177 ----- .../shuffleboard/ShuffleboardContainer.java | 363 --------- .../shuffleboard/ShuffleboardInstance.java | 114 --- .../shuffleboard/ShuffleboardLayout.java | 141 ---- .../shuffleboard/ShuffleboardRoot.java | 45 -- .../wpilibj/shuffleboard/ShuffleboardTab.java | 154 ---- .../shuffleboard/ShuffleboardValue.java | 27 - .../shuffleboard/ShuffleboardWidget.java | 46 -- .../wpilibj/shuffleboard/SimpleWidget.java | 68 -- .../shuffleboard/SuppliedValueWidget.java | 71 -- .../wpilibj/shuffleboard/WidgetType.java | 20 - .../shuffleboard/MockActuatorSendable.java | 22 - .../SendableCameraWrapperTest.java | 65 -- .../ShuffleboardInstanceTest.java | 158 ---- .../shuffleboard/ShuffleboardTest.java | 25 - .../shuffleboard/SuppliedValueWidgetTest.java | 112 --- .../wpi/first/wpilibj/examples/examples.json | 22 +- .../hatchbotinlined/RobotContainer.java | 27 +- .../hatchbottraditional/RobotContainer.java | 32 +- .../wpilibj/examples/shuffleboard/Main.java | 25 - .../wpilibj/examples/shuffleboard/Robot.java | 66 -- .../wpilibj/examples/solenoid/Robot.java | 30 +- .../wpilibj/examples/ultrasonic/Robot.java | 3 +- 82 files changed, 56 insertions(+), 6772 deletions(-) delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/ComplexWidget.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/LayoutType.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/RecordingController.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/SendableCameraWrapper.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/Shuffleboard.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardLayout.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardTab.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/SimpleWidget.cpp delete mode 100644 wpilibc/src/main/native/cpp/shuffleboard/WidgetType.cpp delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/BuiltInLayouts.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/BuiltInWidgets.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/ComplexWidget.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/LayoutType.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/RecordingController.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/SendableCameraWrapper.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/Shuffleboard.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponentBase.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardEventImportance.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardInstance.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardLayout.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardRoot.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardTab.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardValue.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardWidget.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/SimpleWidget.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h delete mode 100644 wpilibc/src/main/native/include/frc/shuffleboard/WidgetType.h delete mode 100644 wpilibc/src/test/native/cpp/shuffleboard/MockActuatorSendable.cpp delete mode 100644 wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp delete mode 100644 wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardTest.cpp delete mode 100644 wpilibc/src/test/native/cpp/shuffleboard/SuppliedValueWidgetTest.cpp delete mode 100644 wpilibc/src/test/native/include/shuffleboard/MockActuatorSendable.h delete mode 100644 wpilibcExamples/src/main/cpp/examples/ShuffleBoard/cpp/Robot.cpp delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/BuiltInLayouts.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/BuiltInWidgets.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ComplexWidget.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ContainerHelper.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/EventImportance.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/LayoutType.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/RecordingController.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SendableCameraWrapper.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/Shuffleboard.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardComponent.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardContainer.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardInstance.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardLayout.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardRoot.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardTab.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardValue.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardWidget.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SimpleWidget.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SuppliedValueWidget.java delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/WidgetType.java delete mode 100644 wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/MockActuatorSendable.java delete mode 100644 wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/SendableCameraWrapperTest.java delete mode 100644 wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardInstanceTest.java delete mode 100644 wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardTest.java delete mode 100644 wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/SuppliedValueWidgetTest.java delete mode 100644 wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/shuffleboard/Main.java delete mode 100644 wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/shuffleboard/Robot.java diff --git a/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp b/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp index 78a3067b388..2a97988b19a 100644 --- a/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp +++ b/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp @@ -14,7 +14,6 @@ #include "frc/DSControlWord.h" #include "frc/Errors.h" #include "frc/livewindow/LiveWindow.h" -#include "frc/shuffleboard/Shuffleboard.h" #include "frc/smartdashboard/SmartDashboard.h" using namespace frc; @@ -153,7 +152,6 @@ void IterativeRobotBase::LoopFunc() { } else if (m_lastMode == Mode::kTest) { if (m_lwEnabledInTest) { LiveWindow::SetEnabled(false); - Shuffleboard::DisableActuatorWidgets(); } TestExit(); } @@ -171,7 +169,6 @@ void IterativeRobotBase::LoopFunc() { } else if (mode == Mode::kTest) { if (m_lwEnabledInTest) { LiveWindow::SetEnabled(true); - Shuffleboard::EnableActuatorWidgets(); } TestInit(); m_watchdog.AddEpoch("TestInit()"); @@ -206,8 +203,6 @@ void IterativeRobotBase::LoopFunc() { m_watchdog.AddEpoch("SmartDashboard::UpdateValues()"); LiveWindow::UpdateValues(); m_watchdog.AddEpoch("LiveWindow::UpdateValues()"); - Shuffleboard::Update(); - m_watchdog.AddEpoch("Shuffleboard::Update()"); if constexpr (IsSimulation()) { HAL_SimPeriodicBefore(); diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ComplexWidget.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ComplexWidget.cpp deleted file mode 100644 index adc015c914f..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/ComplexWidget.cpp +++ /dev/null @@ -1,46 +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. - -#include "frc/shuffleboard/ComplexWidget.h" - -#include - -#include - -#include "frc/smartdashboard/SendableBuilderImpl.h" - -using namespace frc; - -ComplexWidget::ComplexWidget(ShuffleboardContainer& parent, - std::string_view title, wpi::Sendable& sendable) - : ShuffleboardValue(title), - ShuffleboardWidget(parent, title), - m_sendable(sendable) {} - -ComplexWidget::~ComplexWidget() = default; - -void ComplexWidget::EnableIfActuator() { - if (m_builder && static_cast(*m_builder).IsActuator()) { - static_cast(*m_builder).StartLiveWindowMode(); - } -} - -void ComplexWidget::DisableIfActuator() { - if (m_builder && static_cast(*m_builder).IsActuator()) { - static_cast(*m_builder).StopLiveWindowMode(); - } -} - -void ComplexWidget::BuildInto(std::shared_ptr parentTable, - std::shared_ptr metaTable) { - BuildMetadata(metaTable); - if (!m_builder) { - m_builder = std::make_unique(); - static_cast(*m_builder) - .SetTable(parentTable->GetSubTable(GetTitle())); - m_sendable.InitSendable(static_cast(*m_builder)); - static_cast(*m_builder).StartListeners(); - } - m_builder->Update(); -} diff --git a/wpilibc/src/main/native/cpp/shuffleboard/LayoutType.cpp b/wpilibc/src/main/native/cpp/shuffleboard/LayoutType.cpp deleted file mode 100644 index 9c47efb8e9b..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/LayoutType.cpp +++ /dev/null @@ -1,11 +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. - -#include "frc/shuffleboard/LayoutType.h" - -using namespace frc; - -std::string_view LayoutType::GetLayoutName() const { - return m_layoutName; -} diff --git a/wpilibc/src/main/native/cpp/shuffleboard/RecordingController.cpp b/wpilibc/src/main/native/cpp/shuffleboard/RecordingController.cpp deleted file mode 100644 index 90adca62085..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/RecordingController.cpp +++ /dev/null @@ -1,50 +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. - -#include "frc/shuffleboard/RecordingController.h" - -#include - -#include "frc/Errors.h" - -using namespace frc; -using namespace frc::detail; - -RecordingController::RecordingController(nt::NetworkTableInstance ntInstance) { - m_recordingControlEntry = - ntInstance.GetBooleanTopic("/Shuffleboard/.recording/RecordData") - .Publish(); - m_recordingFileNameFormatEntry = - ntInstance.GetStringTopic("/Shuffleboard/.recording/FileNameFormat") - .Publish(); - m_eventsTable = ntInstance.GetTable("/Shuffleboard/.recording/events"); -} - -void RecordingController::StartRecording() { - m_recordingControlEntry.Set(true); -} - -void RecordingController::StopRecording() { - m_recordingControlEntry.Set(false); -} - -void RecordingController::SetRecordingFileNameFormat(std::string_view format) { - m_recordingFileNameFormatEntry.Set(format); -} - -void RecordingController::ClearRecordingFileNameFormat() { - m_recordingFileNameFormatEntry.Set(""); -} - -void RecordingController::AddEventMarker( - std::string_view name, std::string_view description, - ShuffleboardEventImportance importance) { - if (name.empty()) { - FRC_ReportError(err::Error, "Shuffleboard event name was not specified"); - return; - } - m_eventsTable->GetSubTable(name)->GetEntry("Info").SetStringArray( - {{std::string{description}, - std::string{ShuffleboardEventImportanceName(importance)}}}); -} diff --git a/wpilibc/src/main/native/cpp/shuffleboard/SendableCameraWrapper.cpp b/wpilibc/src/main/native/cpp/shuffleboard/SendableCameraWrapper.cpp deleted file mode 100644 index d5e076acb90..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/SendableCameraWrapper.cpp +++ /dev/null @@ -1,32 +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. - -#include "frc/shuffleboard/SendableCameraWrapper.h" - -#include -#include -#include - -#include -#include -#include - -namespace frc { -namespace detail { -std::shared_ptr& GetSendableCameraWrapper( - std::string_view cameraName) { - static wpi::StringMap> wrappers; - return wrappers[cameraName]; -} - -void AddToSendableRegistry(wpi::Sendable* sendable, std::string_view name) { - wpi::SendableRegistry::Add(sendable, name); -} -} // namespace detail - -void SendableCameraWrapper::InitSendable(wpi::SendableBuilder& builder) { - builder.AddStringProperty( - ".ShuffleboardURI", [this] { return m_uri; }, nullptr); -} -} // namespace frc diff --git a/wpilibc/src/main/native/cpp/shuffleboard/Shuffleboard.cpp b/wpilibc/src/main/native/cpp/shuffleboard/Shuffleboard.cpp deleted file mode 100644 index 0fff070d50a..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/Shuffleboard.cpp +++ /dev/null @@ -1,92 +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. - -#include "frc/shuffleboard/Shuffleboard.h" - -#include - -#include - -#include "frc/shuffleboard/ShuffleboardTab.h" - -using namespace frc; - -void Shuffleboard::Update() { - GetInstance().Update(); -} - -ShuffleboardTab& Shuffleboard::GetTab(std::string_view title) { - return GetInstance().GetTab(title); -} - -void Shuffleboard::SelectTab(int index) { - GetInstance().SelectTab(index); -} - -void Shuffleboard::SelectTab(std::string_view title) { - GetInstance().SelectTab(title); -} - -void Shuffleboard::EnableActuatorWidgets() { - GetInstance().EnableActuatorWidgets(); -} - -void Shuffleboard::DisableActuatorWidgets() { - // Need to update to make sure the sendable builders are initialized - Update(); - GetInstance().DisableActuatorWidgets(); -} - -void Shuffleboard::StartRecording() { - GetRecordingController().StartRecording(); -} - -void Shuffleboard::StopRecording() { - GetRecordingController().StopRecording(); -} - -void Shuffleboard::SetRecordingFileNameFormat(std::string_view format) { - GetRecordingController().SetRecordingFileNameFormat(format); -} - -void Shuffleboard::ClearRecordingFileNameFormat() { - GetRecordingController().ClearRecordingFileNameFormat(); -} - -void Shuffleboard::AddEventMarker(std::string_view name, - std::string_view description, - ShuffleboardEventImportance importance) { - GetRecordingController().AddEventMarker(name, description, importance); -} - -void Shuffleboard::AddEventMarker(std::string_view name, - ShuffleboardEventImportance importance) { - AddEventMarker(name, "", importance); -} - -static std::unique_ptr& GetInstanceHolder() { - static std::unique_ptr instance = - std::make_unique( - nt::NetworkTableInstance::GetDefault()); - return instance; -} - -#ifndef __FRC_ROBORIO__ -namespace frc::impl { -void ResetShuffleboardInstance() { - GetInstanceHolder() = std::make_unique( - nt::NetworkTableInstance::GetDefault()); -} -} // namespace frc::impl -#endif - -detail::ShuffleboardInstance& Shuffleboard::GetInstance() { - return *GetInstanceHolder(); -} - -detail::RecordingController& Shuffleboard::GetRecordingController() { - static detail::RecordingController inst( - nt::NetworkTableInstance::GetDefault()); - return inst; -} diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp deleted file mode 100644 index 8dc962e819d..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardComponentBase.cpp +++ /dev/null @@ -1,66 +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. - -#include "frc/shuffleboard/ShuffleboardComponentBase.h" - -#include -#include - -using namespace frc; - -ShuffleboardComponentBase::ShuffleboardComponentBase( - ShuffleboardContainer& parent, std::string_view title, - std::string_view type) - : ShuffleboardValue(title), m_parent(parent), m_type(type) {} - -void ShuffleboardComponentBase::SetType(std::string_view type) { - m_type = type; - m_metadataDirty = true; -} - -void ShuffleboardComponentBase::BuildMetadata( - std::shared_ptr metaTable) { - if (!m_metadataDirty) { - return; - } - // Component type - if (!GetType().empty()) { - metaTable->GetEntry("PreferredComponent").SetString(GetType()); - } - - // Tile size - if (m_width > 0 && m_height > 0) { - metaTable->GetEntry("Size").SetDoubleArray( - {{static_cast(m_width), static_cast(m_height)}}); - } - - // Tile position - if (m_column >= 0 && m_row >= 0) { - metaTable->GetEntry("Position") - .SetDoubleArray( - {{static_cast(m_column), static_cast(m_row)}}); - } - - // Custom properties - if (GetProperties().size() > 0) { - auto propTable = metaTable->GetSubTable("Properties"); - for (auto& entry : GetProperties()) { - propTable->GetEntry(entry.first).SetValue(entry.second); - } - } - m_metadataDirty = false; -} - -ShuffleboardContainer& ShuffleboardComponentBase::GetParent() { - return m_parent; -} - -const std::string& ShuffleboardComponentBase::GetType() const { - return m_type; -} - -const wpi::StringMap& ShuffleboardComponentBase::GetProperties() - const { - return m_properties; -} diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp deleted file mode 100644 index 2b25ef81038..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardContainer.cpp +++ /dev/null @@ -1,404 +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. - -#include "frc/shuffleboard/ShuffleboardContainer.h" - -#include -#include -#include -#include - -#include -#include - -#include "frc/Errors.h" -#include "frc/shuffleboard/ComplexWidget.h" -#include "frc/shuffleboard/ShuffleboardComponent.h" -#include "frc/shuffleboard/ShuffleboardLayout.h" -#include "frc/shuffleboard/SimpleWidget.h" - -using namespace frc; - -static constexpr const char* layoutStrings[] = {"List Layout", "Grid Layout"}; - -static constexpr const char* GetStringFromBuiltInLayout(BuiltInLayouts layout) { - return layoutStrings[static_cast(layout)]; -} - -ShuffleboardContainer::ShuffleboardContainer(std::string_view title) - : ShuffleboardValue(title) {} - -const std::vector>& -ShuffleboardContainer::GetComponents() const { - return m_components; -} - -ShuffleboardLayout& ShuffleboardContainer::GetLayout(std::string_view title, - BuiltInLayouts type) { - return GetLayout(title, GetStringFromBuiltInLayout(type)); -} - -ShuffleboardLayout& ShuffleboardContainer::GetLayout(std::string_view title, - const LayoutType& type) { - return GetLayout(title, type.GetLayoutName()); -} - -ShuffleboardLayout& ShuffleboardContainer::GetLayout(std::string_view title, - std::string_view type) { - if (m_layouts.count(title) == 0) { - auto layout = std::make_unique(*this, title, type); - auto ptr = layout.get(); - m_components.emplace_back(std::move(layout)); - m_layouts.insert(std::pair{title, ptr}); - } - return *m_layouts[title]; -} - -ShuffleboardLayout& ShuffleboardContainer::GetLayout(std::string_view title) { - if (m_layouts.count(title) == 0) { - throw FRC_MakeError(err::InvalidParameter, - "No layout with title {} has been defined", title); - } - return *m_layouts[title]; -} - -ComplexWidget& ShuffleboardContainer::Add(std::string_view title, - wpi::Sendable& sendable) { - CheckTitle(title); - auto widget = std::make_unique(*this, title, sendable); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -ComplexWidget& ShuffleboardContainer::Add(wpi::Sendable& sendable) { - auto name = wpi::SendableRegistry::GetName(&sendable); - if (name.empty()) { - FRC_ReportError(err::Error, "Sendable must have a name"); - } - return Add(name, sendable); -} - -SimpleWidget& ShuffleboardContainer::Add(std::string_view title, - const nt::Value& defaultValue) { - CheckTitle(title); - - auto widget = std::make_unique(*this, title); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - ptr->GetEntry(nt::GetStringFromType(defaultValue.type())) - ->SetDefault(defaultValue); - return *ptr; -} - -SimpleWidget& ShuffleboardContainer::Add(std::string_view title, - bool defaultValue) { - return Add(title, nt::Value::MakeBoolean(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::Add(std::string_view title, - double defaultValue) { - return Add(title, nt::Value::MakeDouble(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::Add(std::string_view title, - float defaultValue) { - return Add(title, nt::Value::MakeFloat(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::Add(std::string_view title, - int defaultValue) { - return Add(title, nt::Value::MakeInteger(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::Add(std::string_view title, - std::string_view defaultValue) { - return Add(title, nt::Value::MakeString(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::Add(std::string_view title, - const char* defaultValue) { - return Add(title, nt::Value::MakeString(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::Add(std::string_view title, - std::span defaultValue) { - return Add(title, nt::Value::MakeBooleanArray(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::Add(std::string_view title, - std::span defaultValue) { - return Add(title, nt::Value::MakeDoubleArray(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::Add(std::string_view title, - std::span defaultValue) { - return Add(title, nt::Value::MakeFloatArray(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::Add( - std::string_view title, std::span defaultValue) { - return Add(title, nt::Value::MakeIntegerArray(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::Add( - std::string_view title, std::span defaultValue) { - return Add(title, nt::Value::MakeStringArray(defaultValue)); -} - -SuppliedValueWidget& ShuffleboardContainer::AddString( - std::string_view title, std::function supplier) { - static auto setter = [](nt::GenericPublisher& entry, std::string value) { - entry.SetString(value); - }; - - CheckTitle(title); - auto widget = std::make_unique>( - *this, title, "string", supplier, setter); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -SuppliedValueWidget& ShuffleboardContainer::AddNumber( - std::string_view title, std::function supplier) { - return AddDouble(title, std::move(supplier)); -} - -SuppliedValueWidget& ShuffleboardContainer::AddDouble( - std::string_view title, std::function supplier) { - static auto setter = [](nt::GenericPublisher& entry, double value) { - entry.SetDouble(value); - }; - - CheckTitle(title); - auto widget = std::make_unique>( - *this, title, "double", supplier, setter); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -SuppliedValueWidget& ShuffleboardContainer::AddFloat( - std::string_view title, std::function supplier) { - static auto setter = [](nt::GenericPublisher& entry, float value) { - entry.SetFloat(value); - }; - - CheckTitle(title); - auto widget = std::make_unique>( - *this, title, "float", supplier, setter); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -SuppliedValueWidget& ShuffleboardContainer::AddInteger( - std::string_view title, std::function supplier) { - static auto setter = [](nt::GenericPublisher& entry, int64_t value) { - entry.SetInteger(value); - }; - - CheckTitle(title); - auto widget = std::make_unique>( - *this, title, "int", supplier, setter); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -SuppliedValueWidget& ShuffleboardContainer::AddBoolean( - std::string_view title, std::function supplier) { - static auto setter = [](nt::GenericPublisher& entry, bool value) { - entry.SetBoolean(value); - }; - - CheckTitle(title); - auto widget = std::make_unique>( - *this, title, "boolean", supplier, setter); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -SuppliedValueWidget>& -ShuffleboardContainer::AddStringArray( - std::string_view title, - std::function()> supplier) { - static auto setter = [](nt::GenericPublisher& entry, - std::vector value) { - entry.SetStringArray(value); - }; - - CheckTitle(title); - auto widget = std::make_unique>>( - *this, title, "string[]", supplier, setter); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -SuppliedValueWidget>& ShuffleboardContainer::AddNumberArray( - std::string_view title, std::function()> supplier) { - return AddDoubleArray(title, std::move(supplier)); -} - -SuppliedValueWidget>& ShuffleboardContainer::AddDoubleArray( - std::string_view title, std::function()> supplier) { - static auto setter = [](nt::GenericPublisher& entry, - std::vector value) { - entry.SetDoubleArray(value); - }; - - CheckTitle(title); - auto widget = std::make_unique>>( - *this, title, "double[]", supplier, setter); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -SuppliedValueWidget>& ShuffleboardContainer::AddFloatArray( - std::string_view title, std::function()> supplier) { - static auto setter = [](nt::GenericPublisher& entry, - std::vector value) { - entry.SetFloatArray(value); - }; - - CheckTitle(title); - auto widget = std::make_unique>>( - *this, title, "float[]", supplier, setter); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -SuppliedValueWidget>& -ShuffleboardContainer::AddIntegerArray( - std::string_view title, std::function()> supplier) { - static auto setter = [](nt::GenericPublisher& entry, - std::vector value) { - entry.SetIntegerArray(value); - }; - - CheckTitle(title); - auto widget = std::make_unique>>( - *this, title, "int[]", supplier, setter); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -SuppliedValueWidget>& ShuffleboardContainer::AddBooleanArray( - std::string_view title, std::function()> supplier) { - static auto setter = [](nt::GenericPublisher& entry, std::vector value) { - entry.SetBooleanArray(value); - }; - - CheckTitle(title); - auto widget = std::make_unique>>( - *this, title, "boolean[]", supplier, setter); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -SuppliedValueWidget>& ShuffleboardContainer::AddRaw( - std::string_view title, std::function()> supplier) { - return AddRaw(title, "raw", std::move(supplier)); -} - -SuppliedValueWidget>& ShuffleboardContainer::AddRaw( - std::string_view title, std::string_view typeString, - std::function()> supplier) { - static auto setter = [](nt::GenericPublisher& entry, - std::vector value) { entry.SetRaw(value); }; - - CheckTitle(title); - auto widget = std::make_unique>>( - *this, title, typeString, supplier, setter); - auto ptr = widget.get(); - m_components.emplace_back(std::move(widget)); - return *ptr; -} - -SimpleWidget& ShuffleboardContainer::AddPersistent( - std::string_view title, const nt::Value& defaultValue) { - auto& widget = Add(title, defaultValue); - widget.GetEntry(nt::GetStringFromType(defaultValue.type())) - ->GetTopic() - .SetPersistent(true); - return widget; -} - -SimpleWidget& ShuffleboardContainer::AddPersistent(std::string_view title, - bool defaultValue) { - return AddPersistent(title, nt::Value::MakeBoolean(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::AddPersistent(std::string_view title, - double defaultValue) { - return AddPersistent(title, nt::Value::MakeDouble(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::AddPersistent(std::string_view title, - float defaultValue) { - return AddPersistent(title, nt::Value::MakeFloat(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::AddPersistent(std::string_view title, - int defaultValue) { - return AddPersistent(title, nt::Value::MakeInteger(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::AddPersistent( - std::string_view title, std::string_view defaultValue) { - return AddPersistent(title, nt::Value::MakeString(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::AddPersistent( - std::string_view title, std::span defaultValue) { - return AddPersistent(title, nt::Value::MakeBooleanArray(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::AddPersistent( - std::string_view title, std::span defaultValue) { - return AddPersistent(title, nt::Value::MakeDoubleArray(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::AddPersistent( - std::string_view title, std::span defaultValue) { - return AddPersistent(title, nt::Value::MakeFloatArray(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::AddPersistent( - std::string_view title, std::span defaultValue) { - return AddPersistent(title, nt::Value::MakeIntegerArray(defaultValue)); -} - -SimpleWidget& ShuffleboardContainer::AddPersistent( - std::string_view title, std::span defaultValue) { - return AddPersistent(title, nt::Value::MakeStringArray(defaultValue)); -} - -void ShuffleboardContainer::EnableIfActuator() { - for (auto& component : GetComponents()) { - component->EnableIfActuator(); - } -} - -void ShuffleboardContainer::DisableIfActuator() { - for (auto& component : GetComponents()) { - component->DisableIfActuator(); - } -} - -void ShuffleboardContainer::CheckTitle(std::string_view title) { - std::string titleStr{title}; - if (m_usedTitles.count(titleStr) > 0) { - FRC_ReportError(err::Error, "Title is already in use: {}", title); - return; - } - m_usedTitles.insert(titleStr); -} diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp deleted file mode 100644 index 0e216c34d34..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardInstance.cpp +++ /dev/null @@ -1,94 +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. - -#include "frc/shuffleboard/ShuffleboardInstance.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "frc/shuffleboard/Shuffleboard.h" - -using namespace frc::detail; - -struct ShuffleboardInstance::Impl { - wpi::StringMap tabs; - - bool tabsChanged = false; - std::shared_ptr rootTable; - std::shared_ptr rootMetaTable; - nt::StringPublisher selectedTabPub; -}; - -ShuffleboardInstance::ShuffleboardInstance(nt::NetworkTableInstance ntInstance) - : m_impl(new Impl) { - m_impl->rootTable = ntInstance.GetTable(Shuffleboard::kBaseTableName); - m_impl->rootMetaTable = m_impl->rootTable->GetSubTable(".metadata"); - m_impl->selectedTabPub = - m_impl->rootMetaTable->GetStringTopic("Selected") - .Publish(nt::PubSubOptions{.keepDuplicates = true}); -} - -ShuffleboardInstance::~ShuffleboardInstance() = default; - -static bool gReported = false; - -frc::ShuffleboardTab& ShuffleboardInstance::GetTab(std::string_view title) { - if (!gReported) { - HAL_Report(HALUsageReporting::kResourceType_Shuffleboard, 0); - gReported = true; - } - auto [it, added] = m_impl->tabs.try_emplace(title, *this, title); - if (added) { - m_impl->tabsChanged = true; - } - return it->second; -} - -void ShuffleboardInstance::Update() { - if (m_impl->tabsChanged) { - wpi::SmallVector tabTitles; - for (auto& entry : m_impl->tabs) { - tabTitles.emplace_back(entry.second.GetTitle()); - } - m_impl->rootMetaTable->GetEntry("Tabs").SetStringArray(tabTitles); - m_impl->tabsChanged = false; - } - for (auto& entry : m_impl->tabs) { - auto& tab = entry.second; - tab.BuildInto(m_impl->rootTable, - m_impl->rootMetaTable->GetSubTable(tab.GetTitle())); - } -} - -void ShuffleboardInstance::EnableActuatorWidgets() { - for (auto& entry : m_impl->tabs) { - auto& tab = entry.second; - for (auto& component : tab.GetComponents()) { - component->EnableIfActuator(); - } - } -} - -void ShuffleboardInstance::DisableActuatorWidgets() { - for (auto& entry : m_impl->tabs) { - auto& tab = entry.second; - for (auto& component : tab.GetComponents()) { - component->DisableIfActuator(); - } - } -} - -void ShuffleboardInstance::SelectTab(int index) { - m_impl->selectedTabPub.Set(std::to_string(index)); -} - -void ShuffleboardInstance::SelectTab(std::string_view title) { - m_impl->selectedTabPub.Set(title); -} diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardLayout.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardLayout.cpp deleted file mode 100644 index da2f71460cc..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardLayout.cpp +++ /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. - -#include "frc/shuffleboard/ShuffleboardLayout.h" - -#include - -#include - -using namespace frc; - -static constexpr std::string_view kSmartDashboardType = "ShuffleboardLayout"; - -ShuffleboardLayout::ShuffleboardLayout(ShuffleboardContainer& parent, - std::string_view title, - std::string_view type) - : ShuffleboardValue(title), - ShuffleboardComponent(parent, title, type), - ShuffleboardContainer(title) { - m_isLayout = true; -} - -void ShuffleboardLayout::BuildInto( - std::shared_ptr parentTable, - std::shared_ptr metaTable) { - BuildMetadata(metaTable); - auto table = parentTable->GetSubTable(GetTitle()); - table->GetEntry(".type").SetString(kSmartDashboardType); - table->GetEntry(".type").GetTopic().SetProperty("SmartDashboard", - kSmartDashboardType); - for (auto& component : GetComponents()) { - component->BuildInto(table, metaTable->GetSubTable(component->GetTitle())); - } -} diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardTab.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardTab.cpp deleted file mode 100644 index 359a63c753b..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardTab.cpp +++ /dev/null @@ -1,32 +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. - -#include "frc/shuffleboard/ShuffleboardTab.h" - -#include - -#include - -using namespace frc; - -static constexpr std::string_view kSmartDashboardType = "ShuffleboardLayout"; - -ShuffleboardTab::ShuffleboardTab(ShuffleboardRoot& root, std::string_view title) - : ShuffleboardValue(title), ShuffleboardContainer(title), m_root(root) {} - -ShuffleboardRoot& ShuffleboardTab::GetRoot() { - return m_root; -} - -void ShuffleboardTab::BuildInto(std::shared_ptr parentTable, - std::shared_ptr metaTable) { - auto tabTable = parentTable->GetSubTable(GetTitle()); - tabTable->GetEntry(".type").SetString(kSmartDashboardType); - tabTable->GetEntry(".type").GetTopic().SetProperty("SmartDashboard", - kSmartDashboardType); - for (auto& component : GetComponents()) { - component->BuildInto(tabTable, - metaTable->GetSubTable(component->GetTitle())); - } -} diff --git a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp b/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp deleted file mode 100644 index bb475fdce52..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/ShuffleboardWidget.cpp +++ /dev/null @@ -1,39 +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. - -#include "frc/shuffleboard/ShuffleboardWidget.h" - -using namespace frc; - -static constexpr const char* widgetStrings[] = { - "Text View", - "Number Slider", - "Number Bar", - "Simple Dial", - "Graph", - "Boolean Box", - "Toggle Button", - "Toggle Switch", - "Voltage View", - "PDP", - "ComboBox Chooser", - "Split Button Chooser", - "Encoder", - "Motor Controller", - "Command", - "PID Command", - "PID Controller", - "Accelerometer", - "3-Axis Accelerometer", - "Gyro", - "Relay", - "Differential Drivebase", - "Mecanum Drivebase", - "Camera Stream", - "Field", -}; - -const char* detail::GetStringForWidgetType(BuiltInWidgets type) { - return widgetStrings[static_cast(type)]; -} diff --git a/wpilibc/src/main/native/cpp/shuffleboard/SimpleWidget.cpp b/wpilibc/src/main/native/cpp/shuffleboard/SimpleWidget.cpp deleted file mode 100644 index 5550136d6d3..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/SimpleWidget.cpp +++ /dev/null @@ -1,51 +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. - -#include "frc/shuffleboard/SimpleWidget.h" - -#include - -#include "frc/shuffleboard/Shuffleboard.h" -#include "frc/shuffleboard/ShuffleboardLayout.h" -#include "frc/shuffleboard/ShuffleboardTab.h" - -using namespace frc; - -SimpleWidget::SimpleWidget(ShuffleboardContainer& parent, - std::string_view title) - : ShuffleboardValue(title), ShuffleboardWidget(parent, title), m_entry() {} - -nt::GenericEntry* SimpleWidget::GetEntry() { - if (!m_entry) { - ForceGenerate(); - } - return &m_entry; -} - -nt::GenericEntry* SimpleWidget::GetEntry(std::string_view typeString) { - if (!m_entry) { - m_typeString = typeString; - ForceGenerate(); - } - return &m_entry; -} - -void SimpleWidget::BuildInto(std::shared_ptr parentTable, - std::shared_ptr metaTable) { - BuildMetadata(metaTable); - if (!m_entry) { - m_entry = parentTable->GetTopic(GetTitle()).GetGenericEntry(m_typeString); - } -} - -void SimpleWidget::ForceGenerate() { - ShuffleboardContainer* parent = &GetParent(); - - while (parent->m_isLayout) { - parent = &(static_cast(parent)->GetParent()); - } - - auto& tab = *static_cast(parent); - tab.GetRoot().Update(); -} diff --git a/wpilibc/src/main/native/cpp/shuffleboard/WidgetType.cpp b/wpilibc/src/main/native/cpp/shuffleboard/WidgetType.cpp deleted file mode 100644 index 3062cba9ad8..00000000000 --- a/wpilibc/src/main/native/cpp/shuffleboard/WidgetType.cpp +++ /dev/null @@ -1,11 +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. - -#include "frc/shuffleboard/WidgetType.h" - -using namespace frc; - -std::string_view WidgetType::GetWidgetName() const { - return m_widgetName; -} diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInLayouts.h b/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInLayouts.h deleted file mode 100644 index ca5e29f37bc..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInLayouts.h +++ /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 "frc/shuffleboard/LayoutType.h" - -namespace frc { - -/** - * The types of layouts bundled with Shuffleboard. - * - *

{@code
- * ShuffleboardLayout myList = Shuffleboard::GetTab("My Tab")
- *   .GetLayout(BuiltinLayouts::kList, "My List");
- * }
- */ -enum class BuiltInLayouts { - /** - * Groups components in a vertical list. New widgets added to the layout will - * be placed at the bottom of the list.
Custom properties: - * - * - * - *
NameTypeDefault ValueNotes
Label positionString"BOTTOM"The position of component labels inside the grid. One of - * {@code ["TOP", "LEFT", "BOTTOM", "RIGHT", "HIDDEN"}
- */ - kList, - - /** - * Groups components in an n x m grid. Grid layouts default to - * 3x3.
Custom properties: - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
Number of columnsNumber3Must be in the - * range [1,15]
Number of rowsNumber3Must be in the - * range [1,15]
Label position String"BOTTOM"The position of component labels inside the grid. - * One of {@code ["TOP", "LEFT", "BOTTOM", "RIGHT", "HIDDEN"}
- */ - kGrid -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInWidgets.h b/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInWidgets.h deleted file mode 100644 index d7ed1d57511..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/BuiltInWidgets.h +++ /dev/null @@ -1,385 +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/shuffleboard/WidgetType.h" - -namespace frc { - -/** - * The types of the widgets bundled with Shuffleboard. - * - *

For example, setting a number to be displayed with a slider: - *

{@code
- * NetworkTableEntry example = Shuffleboard.getTab("My Tab")
- *   .add("My Number", 0)
- *   .withWidget(BuiltInWidgets.kNumberSlider)
- *   .getEntry();
- * }
- * - *

Each value in this enum goes into detail on what data types that widget - * can support, as well as the custom properties that widget uses. - */ -enum class BuiltInWidgets { - /** - * Displays a value with a simple text field. - *
Supported types: - *

- *
This widget has no custom properties. - */ - kTextView, - /** - * Displays a number with a controllable slider. - *
Supported types: - * - *
Custom properties: - * - * - * - *
NameTypeDefault ValueNotes
MinNumber-1.0The minimum value of the - * slider
MaxNumber1.0The maximum - * value of the slider
Block - * incrementNumber0.0625 How much to move the - * slider by with the arrow keys
- */ - kNumberSlider, - /** - * Displays a number with a view-only bar. - *
Supported types: - * - *
Custom properties: - * - * - * - * - *
NameTypeDefault ValueNotes
MinNumber-1.0The minimum value of the - * bar
MaxNumber1.0The maximum - * value of the bar
CenterNumber0The center ("zero") value - * of the bar
- */ - kNumberBar, - /** - * Displays a number with a view-only dial. Displayed values are rounded to - * the nearest integer.
Supported types: - *
Custom properties: - * - * - * - *
NameTypeDefault ValueNotes
MinNumber0The minimum value of the - * dial
MaxNumber100The maximum - * value of the dial
Show - * valueBooleantrue Whether or not to show the - * value as text
- */ - kDial, - /** - * Displays a number with a graph. NOTE: graphs can be taxing - * on the computer running the dashboard. Keep the number of visible data - * points to a minimum. Making the widget smaller also helps with performance, - * but may cause the graph to become difficult to read.
Supported types: - * - *
Custom properties: - * - * - * - * - *
NameTypeDefault ValueNotes
Visible timeNumber30How long, in seconds, should past data be visible for
- */ - kGraph, - /** - * Displays a boolean value as a large colored box. - *
Supported types: - * - *
Custom properties: - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
Color when trueColor"green"Can be specified as a string ({@code "#00FF00"}) or a rgba integer - * ({@code 0x00FF0000}) - *
Color when falseColor"red"Can be specified as a string or a number
- */ - kBooleanBox, - /** - * Displays a boolean with a large interactive toggle button. - *
Supported types: - * - *
This widget has no custom properties. - */ - kToggleButton, - /** - * Displays a boolean with a fixed-size toggle switch. - *
Supported types: - * - *
This widget has no custom properties. - */ - kToggleSwitch, - /** - * Displays an analog input or a raw number with a number bar. - *
Supported types: - * - *
Custom properties: - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
MinNumber0The minimum value of the - * bar
MaxNumber5The maximum - * value of the bar
CenterNumber0The center ("zero") value - * of the bar
OrientationString"HORIZONTAL"The orientation of the bar. One of {@code ["HORIZONTAL", - * "VERTICAL"]}
Number of tick - * marksNumber5 The number of discrete ticks on the - * bar
- */ - kVoltageView, - /** - * Displays a PowerDistribution.
Supported types: - *
Custom properties: - * - * - * - * - *
NameTypeDefault ValueNotes
Show voltage and current valuesBooleantrueWhether or not to display the voltage and current draw
- */ - kPowerDistribution, - /** - * Displays a SendableChooser with a dropdown combo box with a list of - * options. - *
Supported types: - * - *
This widget has no custom properties. - */ - kComboBoxChooser, - /** - * Displays a SendableChooserwith a toggle button for each available option. - *
Supported types: - * - *
This widget has no custom properties. - */ - kSplitButtonChooser, - /** - * Displays an Encoder displaying its speed, - * total traveled distance, and its distance per tick.
Supported types: - * - *
This widget has no custom properties. - */ - kEncoder, - /** - * Displays a MotorController. - * The motor controller will be controllable from the dashboard when test mode - * is enabled, but will otherwise be view-only.
Supported types: - *
Custom properties: - * - * - * - * - *
NameTypeDefault ValueNotes
OrientationString"HORIZONTAL"One of {@code ["HORIZONTAL", "VERTICAL"]}
- */ - kMotorController, - /** - * Displays a command with a toggle button. Pressing the button will start the - * command, and the button will automatically release when the command - * completes.
Supported types: - *
This widget has no custom properties. - */ - kCommand, - /** - * Displays a PID command with a checkbox and an editor for the PIDF - * constants. Selecting the checkbox will start the command, and the checkbox - * will automatically deselect when the command completes.
Supported - * types: - *
This widget has no custom properties. - */ - kPIDCommand, - /** - * Displays a PID controller with an editor for the PIDF constants and a - * toggle switch for enabling and disabling the controller.
Supported - * types: - *
This widget has no custom properties. - */ - kPIDController, - /** - * Displays an accelerometer with a number bar displaying the magnitude of the - * acceleration and text displaying the exact value.
Supported types: - *
Custom properties: - * - * - * - * - * - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
MinNumber-1The minimum acceleration value to display
MaxNumber1The maximum acceleration value to display
Show textBooleantrueShow or hide the acceleration values
PrecisionNumber2How many numbers to display after the decimal point
Show tick marksBooleanfalseShow or hide the tick marks on the number bars
- */ - kAccelerometer, - /** - * Displays a 3-axis accelerometer with a number bar for each axis' - * acceleration.
Supported types: - *
Custom properties: - * - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
RangeRangek16GThe accelerometer - * range
Show valueBooleantrueShow or hide the acceleration values
PrecisionNumber2How many numbers to display after the decimal point
Show tick marksBooleanfalseShow or hide the tick marks on the number bars
- */ - k3AxisAccelerometer, - /** - * Displays a gyro with a dial from 0 to 360 degrees. - *
Supported types: - * - *
Custom properties: - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
Major tick - * spacingNumber45Degrees
Starting angleNumber180How far to rotate the entire dial, in degrees
Show tick mark ringBooleantrue
- */ - kGyro, - /** - * Displays a relay with toggle buttons for each supported mode (off, on, - * forward, reverse).
Supported types: - *
This widget has no custom properties. - */ - kRelay, - /** - * Displays a differential drive with a widget that displays the speed of each - * side of the drivebase and a vector for the direction and rotation of the - * drivebase. The widget will be controllable if the robot is in test mode. - *
Supported types: - * - *
Custom properties: - * - * - * - * - * - *
NameTypeDefault ValueNotes
Number of wheelsNumber4Must be a - * positive even integer - *
Wheel diameterNumber80Pixels
Show velocity vectorsBooleantrue
- */ - kDifferentialDrive, - /** - * Displays a mecanum drive with a widget that displays the speed of each - * wheel, and vectors for the direction and rotation of the drivebase. The - * widget will be controllable if the robot is in test mode.
Supported - * types: - *
Custom properties: - * - * - * - *
NameTypeDefault ValueNotes
Show velocity vectorsBooleantrue
- */ - kMecanumDrive, - /** - * Displays a camera stream. - *
Supported types: - * - *
Custom properties: - * - * - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
Show crosshairBooleantrueShow or hide a crosshair on the image
Crosshair colorColor"white"Can be a string or a rgba integer
Show controlsBooleantrueShow or hide the - * stream controls - *
RotationString"NONE"Rotates the displayed image. One of {@code ["NONE", "QUARTER_CW", - * "QUARTER_CCW", "HALF"]} - *
- */ - kCameraStream, - /** - * Displays a field2d object.
- * Supported types: - * - * - */ - kField, -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ComplexWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/ComplexWidget.h deleted file mode 100644 index a96f879dbaf..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ComplexWidget.h +++ /dev/null @@ -1,46 +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/ShuffleboardWidget.h" - -namespace wpi { -class Sendable; -class SendableBuilder; -} // namespace wpi - -namespace frc { - -class ShuffleboardContainer; - -/** - * A Shuffleboard widget that handles a Sendable object such as a motor - * controller or sensor. - */ -class ComplexWidget final : public ShuffleboardWidget { - public: - ComplexWidget(ShuffleboardContainer& parent, std::string_view title, - wpi::Sendable& sendable); - - ~ComplexWidget() override; - - void EnableIfActuator() override; - - void DisableIfActuator() override; - - void BuildInto(std::shared_ptr parentTable, - std::shared_ptr metaTable) override; - - private: - wpi::Sendable& m_sendable; - std::unique_ptr m_builder; -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/LayoutType.h b/wpilibc/src/main/native/include/frc/shuffleboard/LayoutType.h deleted file mode 100644 index 5fa5ca4ad0c..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/LayoutType.h +++ /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 - -namespace frc { - -/** - * Represents the type of a layout in Shuffleboard. Using this is preferred over - * specifying raw strings, to avoid typos and having to know or look up the - * exact string name for a desired layout. - * - * @see BuiltInLayouts the built-in layout types - */ -class LayoutType { - public: - explicit constexpr LayoutType(const char* layoutName) - : m_layoutName(layoutName) {} - ~LayoutType() = default; - - /** - * Gets the string type of the layout as defined by that layout in - * Shuffleboard. - */ - std::string_view GetLayoutName() const; - - private: - const char* m_layoutName; -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/RecordingController.h b/wpilibc/src/main/native/include/frc/shuffleboard/RecordingController.h deleted file mode 100644 index 3ef51208767..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/RecordingController.h +++ /dev/null @@ -1,40 +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/shuffleboard/ShuffleboardEventImportance.h" - -namespace frc::detail { - -class RecordingController final { - public: - explicit RecordingController(nt::NetworkTableInstance ntInstance); - virtual ~RecordingController() = default; - - void StartRecording(); - void StopRecording(); - void SetRecordingFileNameFormat(std::string_view format); - void ClearRecordingFileNameFormat(); - - void AddEventMarker(std::string_view name, std::string_view description, - ShuffleboardEventImportance importance); - - private: - nt::BooleanPublisher m_recordingControlEntry; - nt::StringPublisher m_recordingFileNameFormatEntry; - std::shared_ptr m_eventsTable; -}; - -} // namespace frc::detail diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/SendableCameraWrapper.h b/wpilibc/src/main/native/include/frc/shuffleboard/SendableCameraWrapper.h deleted file mode 100644 index 7951cf91e04..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/SendableCameraWrapper.h +++ /dev/null @@ -1,136 +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 - -#ifndef DYNAMIC_CAMERA_SERVER -#include -#include -#include -#include -#else -namespace cs { -class VideoSource; -} // namespace cs -using CS_Handle = int; // NOLINT -using CS_Source = CS_Handle; // NOLINT -#endif - -#include -#include -#include - -namespace frc { - -class SendableCameraWrapper; - -namespace detail { -constexpr const char* kProtocol = "camera_server://"; -std::shared_ptr& GetSendableCameraWrapper( - std::string_view cameraName); -void AddToSendableRegistry(wpi::Sendable* sendable, std::string_view name); -} // namespace detail - -/** - * A wrapper to make video sources sendable and usable from Shuffleboard. - */ -class SendableCameraWrapper - : public wpi::Sendable, - public wpi::SendableHelper { - private: - struct private_init {}; - - public: - /** - * Creates a new sendable wrapper. Private constructor to avoid direct - * instantiation with multiple wrappers floating around for the same camera. - * - * @param cameraName the name of the camera to wrap - */ - SendableCameraWrapper(std::string_view cameraName, const private_init&); - - /** - * Creates a new sendable wrapper. Private constructor to avoid direct - * instantiation with multiple wrappers floating around for the same camera. - * - * @param cameraName the name of the camera to wrap - * @param cameraUrls camera URLs - */ - SendableCameraWrapper(std::string_view cameraName, - std::span cameraUrls, - const private_init&); - - /** - * Gets a sendable wrapper object for the given video source, creating the - * wrapper if one does not already exist for the source. - * - * @param source the video source to wrap - * @return a sendable wrapper object for the video source, usable in - * Shuffleboard via ShuffleboardTab::Add() and ShuffleboardLayout::Add() - */ - static SendableCameraWrapper& Wrap(const cs::VideoSource& source); - static SendableCameraWrapper& Wrap(CS_Source source); - - static SendableCameraWrapper& Wrap(std::string_view cameraName, - std::span cameraUrls); - - void InitSendable(wpi::SendableBuilder& builder) override; - - private: - std::string m_uri; - nt::StringArrayPublisher m_streams; -}; - -#ifndef DYNAMIC_CAMERA_SERVER -inline SendableCameraWrapper::SendableCameraWrapper(std::string_view name, - const private_init&) - : m_uri(detail::kProtocol) { - detail::AddToSendableRegistry(this, name); - m_uri += name; -} - -inline SendableCameraWrapper::SendableCameraWrapper( - std::string_view cameraName, std::span cameraUrls, - const private_init&) - : SendableCameraWrapper(cameraName, private_init{}) { - m_streams = nt::NetworkTableInstance::GetDefault() - .GetStringArrayTopic( - fmt::format("/CameraPublisher/{}/streams", cameraName)) - .Publish(); - m_streams.Set(cameraUrls); -} - -inline SendableCameraWrapper& SendableCameraWrapper::Wrap( - const cs::VideoSource& source) { - return Wrap(source.GetHandle()); -} - -inline SendableCameraWrapper& SendableCameraWrapper::Wrap(CS_Source source) { - CS_Status status = 0; - auto name = cs::GetSourceName(source, &status); - auto& wrapper = detail::GetSendableCameraWrapper(name); - if (!wrapper) { - wrapper = std::make_shared(name, private_init{}); - } - return *wrapper; -} - -inline SendableCameraWrapper& SendableCameraWrapper::Wrap( - std::string_view cameraName, std::span cameraUrls) { - auto& wrapper = detail::GetSendableCameraWrapper(cameraName); - if (!wrapper) { - wrapper = std::make_shared(cameraName, cameraUrls, - private_init{}); - } - return *wrapper; -} -#endif - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/Shuffleboard.h b/wpilibc/src/main/native/include/frc/shuffleboard/Shuffleboard.h deleted file mode 100644 index 252d74ab2ca..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/Shuffleboard.h +++ /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 "frc/shuffleboard/RecordingController.h" -#include "frc/shuffleboard/ShuffleboardEventImportance.h" -#include "frc/shuffleboard/ShuffleboardInstance.h" - -namespace frc { - -class ShuffleboardTab; - -/** - * The Shuffleboard class provides a mechanism with which data can be added and - * laid out in the Shuffleboard dashboard application from a robot program. Tabs - * and layouts can be specified, as well as choosing which widgets to display - * with and setting properties of these widgets; for example, programmers can - * specify a specific {@code boolean} value to be displayed with a toggle button - * instead of the default colored box, or set custom colors for that box. - * - * For example, displaying a boolean entry with a toggle button: - *
{@code
- * NetworkTableEntry myBoolean = Shuffleboard.getTab("Example Tab")
- *   .add("My Boolean", false)
- *   .withWidget("Toggle Button")
- *   .getEntry();
- * }
- * - * Changing the colors of the boolean box: - *
{@code
- * NetworkTableEntry myBoolean = Shuffleboard.getTab("Example Tab")
- *   .add("My Boolean", false)
- *   .withWidget("Boolean Box")
- *   .withProperties(Map.of("colorWhenTrue", "green", "colorWhenFalse",
- * "maroon")) .getEntry();
- * }
- * - * Specifying a parent layout. Note that the layout type must always be - * specified, even if the layout has already been generated by a previously - * defined entry. - *
{@code
- * NetworkTableEntry myBoolean = Shuffleboard.getTab("Example Tab")
- *   .getLayout("List", "Example List")
- *   .add("My Boolean", false)
- *   .withWidget("Toggle Button")
- *   .getEntry();
- * }
- *

- * - * Teams are encouraged to set up shuffleboard layouts at the start of the robot - * program. - */ -class Shuffleboard final { - public: - /** - * The name of the base NetworkTable into which all Shuffleboard data will be - * added. - */ - static constexpr const char* kBaseTableName = "/Shuffleboard"; - - /** - * Updates all the values in Shuffleboard. Iterative and timed robots are - * pre-configured to call this method in the main robot loop; teams using - * custom robot base classes, or subclass SampleRobot, should make sure to - * call this repeatedly to keep data on the dashboard up to date. - */ - static void Update(); - - /** - * Gets the Shuffleboard tab with the given title, creating it if it does not - * already exist. - * - * @param title the title of the tab - * @return the tab with the given title - */ - static ShuffleboardTab& GetTab(std::string_view title); - - /** - * Selects the tab in the dashboard with the given index in the range - * [0..n-1], where n is the number of tabs in the dashboard at the time - * this method is called. - * - * @param index the index of the tab to select - */ - static void SelectTab(int index); - - /** - * Selects the tab in the dashboard with the given title. - * - * @param title the title of the tab to select - */ - static void SelectTab(std::string_view title); - - /** - * Enables user control of widgets containing actuators: motor controllers, - * relays, etc. This should only be used when the robot is in test mode. - * IterativeRobotBase and SampleRobot are both configured to call this method - * when entering test mode; most users should not need to use this method - * directly. - */ - static void EnableActuatorWidgets(); - - /** - * Disables user control of widgets containing actuators. For safety reasons, - * actuators should only be controlled while in test mode. IterativeRobotBase - * and SampleRobot are both configured to call this method when exiting in - * test mode; most users should not need to use this method directly. - */ - static void DisableActuatorWidgets(); - - /** - * Starts data recording on the dashboard. Has no effect if recording is - * already in progress. - */ - static void StartRecording(); - - /** - * Stops data recording on the dashboard. Has no effect if no recording is in - * progress. - */ - static void StopRecording(); - - /** - * Sets the file name format for new recording files to use. If recording is - * in progress when this method is called, it will continue to use the same - * file. New recordings will use the format. - * - *

To avoid recording files overwriting each other, make sure to use unique - * recording file names. File name formats accept templates for inserting the - * date and time when the recording started with the {@code ${date}} and - * {@code ${time}} templates, respectively. For example, the default format is - * {@code "recording-${time}"} and recording files created with it will have - * names like {@code "recording-2018.01.15.sbr"}. Users are - * strongly recommended to use the {@code ${time}} template - * to ensure unique file names. - *

- * - * @param format the format for the - */ - static void SetRecordingFileNameFormat(std::string_view format); - - /** - * Clears the custom name format for recording files. New recordings will use - * the default format. - * - * @see SetRecordingFileNameFormat(std::string_view) - */ - static void ClearRecordingFileNameFormat(); - - /** - * Notifies Shuffleboard of an event. Events can range from as trivial as a - * change in a command state to as critical as a total power loss or component - * failure. If Shuffleboard is recording, the event will also be recorded. - * - *

If {@code name} is {@code null} or empty, no event will be sent and an - * error will be printed to the driver station. - * - * @param name the name of the event - * @param description a description of the event - * @param importance the importance of the event - */ - static void AddEventMarker(std::string_view name, - std::string_view description, - ShuffleboardEventImportance importance); - - /** - * Notifies Shuffleboard of an event. Events can range from as trivial as a - * change in a command state to as critical as a total power loss or component - * failure. If Shuffleboard is recording, the event will also be recorded. - * - *

If {@code name} is {@code null} or empty, no event will be sent and an - * error will be printed to the driver station. - * - * @param name the name of the event - * @param importance the importance of the event - */ - static void AddEventMarker(std::string_view name, - ShuffleboardEventImportance importance); - - private: - static detail::ShuffleboardInstance& GetInstance(); - static detail::RecordingController& GetRecordingController(); - - // TODO usage reporting - - Shuffleboard() = default; -}; - -} // namespace frc - -// Make use of references returned by member functions usable -#include "frc/shuffleboard/ShuffleboardTab.h" diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h deleted file mode 100644 index 3441c5784df..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponent.h +++ /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/shuffleboard/ShuffleboardComponentBase.h" - -namespace frc { - -class ShuffleboardContainer; - -/** - * A generic component in Shuffleboard. - * - * @tparam Derived the self type - */ -template -class ShuffleboardComponent : public ShuffleboardComponentBase { - public: - /** - * Constructs a ShuffleboardComponent. - * - * @param parent The parent container. - * @param title The component title. - * @param type The component type. - */ - ShuffleboardComponent(ShuffleboardContainer& parent, std::string_view title, - std::string_view type = "") - : ShuffleboardValue(title), - ShuffleboardComponentBase(parent, title, type) {} - - /** - * Sets custom properties for this component. Property names are - * case-sensitive and whitespace-insensitive (capitalization and spaces do not - * matter). - * - * @param properties the properties for this component - * @return this component - */ - 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 - * component is inside a layout. - * - * If the position of a single component is set, it is recommended to set the - * positions of all components inside a tab to prevent Shuffleboard - * from automatically placing another component there before the one with the - * specific position is sent. - * - * @param columnIndex the column in the tab to place this component - * @param rowIndex the row in the tab to place this component - * @return this component - */ - 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 - * component is inside a layout. - * - * @param width how many columns wide the component should be - * @param height how many rows high the component should be - * @return this component - */ - Derived& 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/ShuffleboardComponentBase.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponentBase.h deleted file mode 100644 index de27b3528a0..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardComponentBase.h +++ /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 -#include -#include - -#include "frc/shuffleboard/ShuffleboardValue.h" - -namespace frc { - -class ShuffleboardContainer; - -/** - * A shim class to allow storing ShuffleboardComponents in arrays. - */ -class ShuffleboardComponentBase : public virtual ShuffleboardValue { - public: - ShuffleboardComponentBase(ShuffleboardContainer& parent, - std::string_view title, std::string_view type = ""); - - void SetType(std::string_view type); - - void BuildMetadata(std::shared_ptr metaTable); - - ShuffleboardContainer& GetParent(); - - const std::string& GetType() const; - - protected: - wpi::StringMap m_properties; - bool m_metadataDirty = true; - int m_column = -1; - int m_row = -1; - int m_width = -1; - int m_height = -1; - - private: - ShuffleboardContainer& m_parent; - std::string m_type; - - /** - * Gets the custom properties for this component. May be null. - */ - const wpi::StringMap& GetProperties() const; -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h deleted file mode 100644 index 5d207838208..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardContainer.h +++ /dev/null @@ -1,727 +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 -#include - -#include "frc/shuffleboard/BuiltInLayouts.h" -#include "frc/shuffleboard/LayoutType.h" -#include "frc/shuffleboard/ShuffleboardComponentBase.h" -#include "frc/shuffleboard/ShuffleboardValue.h" -#include "frc/shuffleboard/SuppliedValueWidget.h" - -namespace cs { -class VideoSource; -} // namespace cs - -namespace wpi { -class Sendable; -} // namespace wpi - -namespace frc { - -class ComplexWidget; -class ShuffleboardLayout; -class SimpleWidget; - -/** - * Common interface for objects that can contain shuffleboard components. - */ -class ShuffleboardContainer : public virtual ShuffleboardValue { - public: - explicit ShuffleboardContainer(std::string_view title); - - ShuffleboardContainer(ShuffleboardContainer&& rhs) = default; - - ~ShuffleboardContainer() override = default; - - /** - * Gets the components that are direct children of this container. - */ - const std::vector>& GetComponents() - const; - - /** - * Gets the layout with the given type and title, creating it if it does not - * already exist at the time this method is called. - * - * @param title the title of the layout - * @param type the type of the layout, eg "List" or "Grid" - * @return the layout - */ - ShuffleboardLayout& GetLayout(std::string_view title, BuiltInLayouts type); - - /** - * Gets the layout with the given type and title, creating it if it does not - * already exist at the time this method is called. - * - * @param title the title of the layout - * @param type the type of the layout, eg "List" or "Grid" - * @return the layout - */ - ShuffleboardLayout& GetLayout(std::string_view title, const LayoutType& type); - - /** - * Gets the layout with the given type and title, creating it if it does not - * already exist at the time this method is called. Note: this method should - * only be used to use a layout type that is not already built into - * Shuffleboard. To use a layout built into Shuffleboard, use - * GetLayout(std::string_view, const LayoutType&) and the layouts in - * BuiltInLayouts. - * - * @param title the title of the layout - * @param type the type of the layout, eg "List Layout" or "Grid Layout" - * @return the layout - * @see GetLayout(std::string_view, const LayoutType&) - */ - ShuffleboardLayout& GetLayout(std::string_view title, std::string_view type); - - /** - * Gets the already-defined layout in this container with the given title. - * - *

{@code
-   * Shuffleboard::GetTab("Example Tab")->getLayout("My Layout",
-   * &BuiltInLayouts.kList);
-   *
-   * // Later...
-   * Shuffleboard::GetTab("Example Tab")->GetLayout("My Layout");
-   * }
- * - * @param title the title of the layout to get - * @return the layout with the given title - * @throws if no layout has yet been defined with the given title - */ - ShuffleboardLayout& GetLayout(std::string_view title); - - /** - * Adds a widget to this container to display the given sendable. - * - * @param title the title of the widget - * @param sendable the sendable to display - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - */ - ComplexWidget& Add(std::string_view title, wpi::Sendable& sendable); - - /** - * Adds a widget to this container to display the given video stream. - * - * @param title the title of the widget - * @param video the video stream to display - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - */ - ComplexWidget& Add(std::string_view title, const cs::VideoSource& video); - - /** - * Adds a widget to this container to display a video stream. - * - * @param title the title of the widget - * @param cameraName the name of the streamed camera - * @param cameraUrls the URLs with which the dashboard can access the camera - * stream - * @return a widget to display the camera stream - */ - ComplexWidget& AddCamera(std::string_view title, std::string_view cameraName, - std::span cameraUrls); - - /** - * Adds a widget to this container to display the given sendable. - * - * @param sendable the sendable to display - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title, or if the sendable's name has not been - * specified - */ - ComplexWidget& Add(wpi::Sendable& sendable); - - /** - * Adds a widget to this container to display the given video stream. - * - * @param video the video to display - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the same title as the video source - */ - ComplexWidget& Add(const cs::VideoSource& video); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, std::shared_ptr) - * Add(std::string_view title, std::shared_ptr defaultValue) - */ - SimpleWidget& Add(std::string_view title, const nt::Value& defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, bool) - * Add(std::string_view title, bool defaultValue) - */ - SimpleWidget& Add(std::string_view title, bool defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, double) - * Add(std::string_view title, double defaultValue) - */ - SimpleWidget& Add(std::string_view title, double defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, double) - * Add(std::string_view title, double defaultValue) - */ - SimpleWidget& Add(std::string_view title, float defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, int) - * Add(std::string_view title, int defaultValue) - */ - SimpleWidget& Add(std::string_view title, int defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, std::string_view) - * Add(std::string_view title, std::string_view defaultValue) - */ - SimpleWidget& Add(std::string_view title, std::string_view defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, const char*) - * Add(std::string_view title, const char* defaultValue) - */ - SimpleWidget& Add(std::string_view title, const char* defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, std::span) - * Add(std::string_view title, std::span defaultValue) - */ - SimpleWidget& Add(std::string_view title, std::span defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, std::span) - * Add(std::string_view title, std::span defaultValue) - */ - SimpleWidget& Add(std::string_view title, - std::span defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, std::span) - * Add(std::string_view title, std::span defaultValue) - */ - SimpleWidget& Add(std::string_view title, - std::span defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, std::span) - * Add(std::string_view title, std::span defaultValue) - */ - SimpleWidget& Add(std::string_view title, - std::span defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this - * container with the given title - * @see AddPersistent(std::string_view, std::span) - * Add(std::string_view title, std::span defaultValue) - */ - SimpleWidget& Add(std::string_view title, - std::span defaultValue); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget& AddString( - std::string_view title, std::function supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget& AddNumber(std::string_view title, - std::function supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget& AddDouble(std::string_view title, - std::function supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget& AddFloat(std::string_view title, - std::function supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget& AddInteger(std::string_view title, - std::function supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget& AddBoolean(std::string_view title, - std::function supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget>& AddStringArray( - std::string_view title, - std::function()> supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget>& AddNumberArray( - std::string_view title, std::function()> supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget>& AddDoubleArray( - std::string_view title, std::function()> supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget>& AddFloatArray( - std::string_view title, std::function()> supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget>& AddIntegerArray( - std::string_view title, std::function()> supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget>& AddBooleanArray( - std::string_view title, std::function()> supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget>& AddRaw( - std::string_view title, std::function()> supplier); - - /** - * Adds a widget to this container. The widget will display the data provided - * by the value supplier. Changes made on the dashboard will not propagate to - * the widget object, and will be overridden by values from the value - * supplier. - * - * @param title the title of the widget - * @param typeString the NT type string - * @param supplier the supplier for values - * @return a widget to display data - */ - SuppliedValueWidget>& AddRaw( - std::string_view title, std::string_view typeString, - std::function()> supplier); - - /** - * Adds a widget to this container to display a simple piece of data. - * - * Unlike Add(std::string_view, std::shared_ptr), the value in the - * widget will be saved on the robot and will be used when the robot program - * next starts rather than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @see Add(stdd::string_view, std::shared_ptr) - * Add(std::string_view title, std::shared_ptr defaultValue) - */ - SimpleWidget& AddPersistent(std::string_view title, - const nt::Value& defaultValue); - - /** - * Adds a widget to this container to display a simple piece of data. - * - * Unlike Add(std::string_view, bool), the value in the widget will be saved - * on the robot and will be used when the robot program next starts rather - * than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @see Add(std::string_view, bool) - * Add(std::string_view title, bool defaultValue) - */ - SimpleWidget& AddPersistent(std::string_view title, bool defaultValue); - - /** - * Adds a widget to this container to display a simple piece of data. - * - * Unlike Add(std::string_view, double), the value in the widget will be saved - * on the robot and will be used when the robot program next starts rather - * than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @see Add(std::string_view, double) - * Add(std::string_view title, double defaultValue) - */ - SimpleWidget& AddPersistent(std::string_view title, double defaultValue); - - /** - * Adds a widget to this container to display a simple piece of data. - * - * Unlike Add(std::string_view, float), the value in the widget will be saved - * on the robot and will be used when the robot program next starts rather - * than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @see Add(std::string_view, float) - * Add(std::string_view title, float defaultValue) - */ - SimpleWidget& AddPersistent(std::string_view title, float defaultValue); - - /** - * Adds a widget to this container to display a simple piece of data. - * - * Unlike Add(std::string_view, int64_t), the value in the widget will be - * saved on the robot and will be used when the robot program next starts - * rather than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @see Add(std:string_view, int64_t) - * Add(std::string_view title, int64_t defaultValue) - */ - SimpleWidget& AddPersistent(std::string_view title, int defaultValue); - - /** - * Adds a widget to this container to display a simple piece of data. - * - * Unlike Add(std::string_view, std::string_view), the value in the widget - * will be saved on the robot and will be used when the robot program next - * starts rather than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @see Add(std::string_view, std::string_view) - * Add(std::string_view title, std::string_view defaultValue) - */ - SimpleWidget& AddPersistent(std::string_view title, - std::string_view defaultValue); - - /** - * Adds a widget to this container to display a simple piece of data. - * - * Unlike Add(std::string_view, std::span), the value in the - * widget will be saved on the robot and will be used when the robot program - * next starts rather than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @see Add(std::string_view, std::span) - * Add(std::string_view title, std::span defaultValue) - */ - SimpleWidget& AddPersistent(std::string_view title, - std::span defaultValue); - - /** - * Adds a widget to this container to display a simple piece of data. - * - * Unlike Add(std::string_view, std::span), the value in the - * widget will be saved on the robot and will be used when the robot program - * next starts rather than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @see Add(std::string_view, std::span) - * Add(std::string_view title, std::span defaultValue) - */ - SimpleWidget& AddPersistent(std::string_view title, - std::span defaultValue); - - /** - * Adds a widget to this container to display a simple piece of data. - * - * Unlike Add(std::string_view, std::span), the value in the - * widget will be saved on the robot and will be used when the robot program - * next starts rather than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @see Add(std::string_view, std::span) - * Add(std::string_view title, std::span defaultValue) - */ - SimpleWidget& AddPersistent(std::string_view title, - std::span defaultValue); - - /** - * Adds a widget to this container to display a simple piece of data. - * - * Unlike Add(std::string_view, std::span), the value in the - * widget will be saved on the robot and will be used when the robot program - * next starts rather than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @see Add(std::string_view, std::span) - * Add(std::string_view title, std::span defaultValue) - */ - SimpleWidget& AddPersistent(std::string_view title, - std::span defaultValue); - - /** - * Adds a widget to this container to display a simple piece of data. - * - * Unlike Add(std::string_view, std::span), the value in - * the widget will be saved on the robot and will be used when the robot - * program next starts rather than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @see Add(std::string_view, std::span) - * Add(std::string_view title, std::span defaultValue) - */ - SimpleWidget& AddPersistent(std::string_view title, - std::span defaultValue); - - void EnableIfActuator() override; - - void DisableIfActuator() override; - - protected: - bool m_isLayout = false; - - private: - wpi::SmallSet m_usedTitles; - std::vector> m_components; - wpi::StringMap m_layouts; - - /** - * Adds title to internal set if it hasn't already. - * - * @return True if title isn't in use; false otherwise. - */ - void CheckTitle(std::string_view title); - - friend class SimpleWidget; -}; - -} // namespace frc - -// Make use of references returned by member functions usable -#include "frc/shuffleboard/ComplexWidget.h" -#include "frc/shuffleboard/ShuffleboardLayout.h" -#include "frc/shuffleboard/SimpleWidget.h" - -#ifndef DYNAMIC_CAMERA_SERVER -#include "frc/shuffleboard/SendableCameraWrapper.h" - -inline frc::ComplexWidget& frc::ShuffleboardContainer::Add( - const cs::VideoSource& video) { - return Add(frc::SendableCameraWrapper::Wrap(video)); -} - -inline frc::ComplexWidget& frc::ShuffleboardContainer::Add( - std::string_view title, const cs::VideoSource& video) { - return Add(title, frc::SendableCameraWrapper::Wrap(video)); -} - -inline frc::ComplexWidget& frc::ShuffleboardContainer::AddCamera( - std::string_view title, std::string_view cameraName, - std::span cameraUrls) { - return Add(title, frc::SendableCameraWrapper::Wrap(cameraName, cameraUrls)); -} -#endif diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardEventImportance.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardEventImportance.h deleted file mode 100644 index ea251ec9158..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardEventImportance.h +++ /dev/null @@ -1,40 +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 - -namespace frc { - -// Maintainer note: this enum is mirrored in WPILibJ and in Shuffleboard -// Modifying the enum or enum strings requires a corresponding change to the -// Java enum and the enum in Shuffleboard - -enum ShuffleboardEventImportance { kTrivial, kLow, kNormal, kHigh, kCritical }; - -/** - * Returns name of the given enum. - * - * @return Name of the given enum. - */ -inline std::string_view ShuffleboardEventImportanceName( - ShuffleboardEventImportance importance) { - switch (importance) { - case kTrivial: - return "TRIVIAL"; - case kLow: - return "LOW"; - case kNormal: - return "NORMAL"; - case kHigh: - return "HIGH"; - case kCritical: - return "CRITICAL"; - default: - return "NORMAL"; - } -} - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardInstance.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardInstance.h deleted file mode 100644 index 2885af7b8a5..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardInstance.h +++ /dev/null @@ -1,40 +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/shuffleboard/ShuffleboardRoot.h" -#include "frc/shuffleboard/ShuffleboardTab.h" - -namespace frc::detail { - -class ShuffleboardInstance final : public ShuffleboardRoot { - public: - explicit ShuffleboardInstance(nt::NetworkTableInstance ntInstance); - virtual ~ShuffleboardInstance(); - - ShuffleboardInstance(ShuffleboardInstance&&) = default; - ShuffleboardInstance& operator=(ShuffleboardInstance&&) = default; - - frc::ShuffleboardTab& GetTab(std::string_view title) override; - - void Update() override; - - void EnableActuatorWidgets() override; - - void DisableActuatorWidgets() override; - - void SelectTab(int index) override; - - void SelectTab(std::string_view) override; - - private: - struct Impl; - std::unique_ptr m_impl; -}; - -} // namespace frc::detail diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardLayout.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardLayout.h deleted file mode 100644 index fe9e102be83..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardLayout.h +++ /dev/null @@ -1,40 +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" -#include "frc/shuffleboard/ShuffleboardContainer.h" - -#ifdef _WIN32 -#pragma warning(push) -#pragma warning(disable : 4250) -#endif - -namespace frc { - -/** - * A layout in a Shuffleboard tab. Layouts can contain widgets and other - * layouts. - */ -class ShuffleboardLayout : public ShuffleboardComponent, - public ShuffleboardContainer { - public: - ShuffleboardLayout(ShuffleboardContainer& parent, std::string_view name, - std::string_view type); - - void BuildInto(std::shared_ptr parentTable, - std::shared_ptr metaTable) override; -}; - -} // namespace frc - -#ifdef _WIN32 -#pragma warning(pop) -#endif diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardRoot.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardRoot.h deleted file mode 100644 index 1e766a84e46..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardRoot.h +++ /dev/null @@ -1,63 +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 - -namespace frc { - -class ShuffleboardTab; - -/** - * The root of the data placed in Shuffleboard. It contains the tabs, but no - * data is placed directly in the root. - * - * This class is package-private to minimize API surface area. - */ -class ShuffleboardRoot { - public: - /** - * Gets the tab with the given title, creating it if it does not already - * exist. - * - * @param title the title of the tab - * @return the tab with the given title - */ - virtual ShuffleboardTab& GetTab(std::string_view title) = 0; - - /** - * Updates all tabs. - */ - virtual void Update() = 0; - - /** - * Enables all widgets in Shuffleboard that offer user control over actuators. - */ - virtual void EnableActuatorWidgets() = 0; - - /** - * Disables all widgets in Shuffleboard that offer user control over - * actuators. - */ - virtual void DisableActuatorWidgets() = 0; - - /** - * Selects the tab in the dashboard with the given index in the range - * [0..n-1], where n is the number of tabs in the dashboard at the time - * this method is called. - * - * @param index the index of the tab to select - */ - virtual void SelectTab(int index) = 0; - - /** - * Selects the tab in the dashboard with the given title. - * - * @param title the title of the tab to select - */ - virtual void SelectTab(std::string_view title) = 0; -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardTab.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardTab.h deleted file mode 100644 index 8864cdb97dd..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardTab.h +++ /dev/null @@ -1,39 +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/ShuffleboardContainer.h" - -namespace frc { - -class ShuffleboardRoot; - -/** - * Represents a tab in the Shuffleboard dashboard. Widgets can be added to the - * tab with Add(Sendable), Add(std::string_view, Object), and - * Add(String, Sendable). Widgets can also be added to layouts with - * GetLayout(std::string_view, std::string_view); layouts can be nested - * arbitrarily deep (note that too many levels may make deeper components - * unusable). - */ -class ShuffleboardTab final : public ShuffleboardContainer { - public: - ShuffleboardTab(ShuffleboardRoot& root, std::string_view title); - - ShuffleboardRoot& GetRoot(); - - void BuildInto(std::shared_ptr parentTable, - std::shared_ptr metaTable) override; - - private: - ShuffleboardRoot& m_root; -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardValue.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardValue.h deleted file mode 100644 index 4b7ccd46e76..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardValue.h +++ /dev/null @@ -1,67 +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 - -namespace frc { - -class ShuffleboardValue { - public: - explicit ShuffleboardValue(std::string_view title) : m_title(title) {} - - virtual ~ShuffleboardValue() = default; - - ShuffleboardValue(const ShuffleboardValue&) = delete; - ShuffleboardValue& operator=(const ShuffleboardValue&) = delete; - - /** - * Gets the title of this Shuffleboard value. - */ - const std::string& GetTitle() const { return m_title; } - - /** - * Builds the entries for this value. - * - * @param parentTable The table containing all the data for the parent. Values - * that require a complex entry or table structure should - * call {@code parentTable.getSubtable(getTitle())} to get - * the table to put data into. Values that only use a - * single entry should call - * {@code parentTable.getEntry(getTitle())} to get that - * entry. - * @param metaTable The table containing all the metadata for this value and - * its sub-values - */ - virtual void BuildInto(std::shared_ptr parentTable, - std::shared_ptr metaTable) = 0; - - /** - * Enables user control of this widget in the Shuffleboard application. - * - * This method is package-private to prevent users from enabling control - * themselves. Has no effect if the sendable is not marked as an actuator with - * SendableBuilder::SetActuator(). - */ - virtual void EnableIfActuator() {} - - /** - * Disables user control of this widget in the Shuffleboard application. - * - * This method is package-private to prevent users from enabling control - * themselves. Has no effect if the sendable is not marked as an actuator with - * SendableBuilder::SetActuator(). - */ - virtual void DisableIfActuator() {} - - private: - std::string m_title; -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardWidget.h deleted file mode 100644 index ce01367074a..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/ShuffleboardWidget.h +++ /dev/null @@ -1,74 +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/shuffleboard/BuiltInWidgets.h" -#include "frc/shuffleboard/ShuffleboardComponent.h" -#include "frc/shuffleboard/WidgetType.h" - -namespace frc { - -class ShuffleboardContainer; - -namespace detail { -const char* GetStringForWidgetType(BuiltInWidgets type); -} // namespace detail - -/** - * Abstract superclass for widgets. - * - *

This class is package-private to minimize API surface area. - * - * @tparam Derived the self type - */ -template -class ShuffleboardWidget : public ShuffleboardComponent { - public: - ShuffleboardWidget(ShuffleboardContainer& parent, std::string_view title) - : ShuffleboardValue(title), - ShuffleboardComponent(parent, title) {} - - /** - * Sets the type of widget used to display the data. If not set, the default - * widget type will be used. - * - * @param widgetType the type of the widget used to display the data - * @return this widget object - * @see BuiltInWidgets - */ - Derived& WithWidget(BuiltInWidgets widgetType) { - return WithWidget(detail::GetStringForWidgetType(widgetType)); - } - - /** - * Sets the type of widget used to display the data. If not set, the default - * widget type will be used. - * - * @param widgetType the type of the widget used to display the data - * @return this widget object - */ - Derived& WithWidget(const WidgetType& widgetType) { - return WithWidget(widgetType.GetWidgetName()); - } - - /** - * Sets the type of widget used to display the data. If not set, the default - * widget type will be used. This method should only be used to use a widget - * that does not come built into Shuffleboard (i.e. one that comes with a - * custom or third-party plugin). To use a widget that is built into - * Shuffleboard, use WithWidget(WidgetType) and BuiltInWidgets. - * - * @param widgetType the type of the widget used to display the data - * @return this widget object - */ - Derived& WithWidget(std::string_view widgetType) { - this->SetType(widgetType); - return *static_cast(this); - } -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/SimpleWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/SimpleWidget.h deleted file mode 100644 index 97502be5ad9..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/SimpleWidget.h +++ /dev/null @@ -1,54 +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 "frc/shuffleboard/ShuffleboardWidget.h" - -namespace frc { - -class ShuffleboardContainer; - -/** - * A Shuffleboard widget that handles a single data point such as a number or - * string. - */ -class SimpleWidget final : public ShuffleboardWidget { - public: - SimpleWidget(ShuffleboardContainer& parent, std::string_view title); - - /** - * Gets the NetworkTable entry that contains the data for this widget. - * The widget owns the entry; the returned pointer's lifetime is the same as - * that of the widget. - */ - nt::GenericEntry* GetEntry(); - - /** - * Gets the NetworkTable entry that contains the data for this widget. - * The widget owns the entry; the returned pointer's lifetime is the same as - * that of the widget. - * - * @param typeString NT type string - */ - nt::GenericEntry* GetEntry(std::string_view typeString); - - void BuildInto(std::shared_ptr parentTable, - std::shared_ptr metaTable) override; - - private: - nt::GenericEntry m_entry; - std::string m_typeString; - - void ForceGenerate(); -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h b/wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h deleted file mode 100644 index c044f25d351..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/SuppliedValueWidget.h +++ /dev/null @@ -1,58 +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 "frc/shuffleboard/ShuffleboardComponent.h" -#include "frc/shuffleboard/ShuffleboardComponentBase.h" -#include "frc/shuffleboard/ShuffleboardWidget.h" - -namespace frc { -class ShuffleboardContainer; - -template -class SuppliedValueWidget : public ShuffleboardWidget> { - public: - SuppliedValueWidget(ShuffleboardContainer& parent, std::string_view title, - std::string_view typeString, std::function supplier, - std::function setter) - : ShuffleboardValue(title), - ShuffleboardWidget>(parent, title), - m_typeString(typeString), - m_supplier(supplier), - m_setter(setter) {} - - void BuildInto(std::shared_ptr parentTable, - std::shared_ptr metaTable) override { - this->BuildMetadata(metaTable); - if (!m_controllablePub) { - m_controllablePub = - nt::BooleanTopic{metaTable->GetTopic("Controllable")}.Publish(); - m_controllablePub.Set(false); - } - - if (!m_entry) { - m_entry = - parentTable->GetTopic(this->GetTitle()).GenericPublish(m_typeString); - } - m_setter(m_entry, m_supplier()); - } - - private: - std::string m_typeString; - std::function m_supplier; - std::function m_setter; - nt::BooleanPublisher m_controllablePub; - nt::GenericPublisher m_entry; -}; -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/shuffleboard/WidgetType.h b/wpilibc/src/main/native/include/frc/shuffleboard/WidgetType.h deleted file mode 100644 index 13805bb85ec..00000000000 --- a/wpilibc/src/main/native/include/frc/shuffleboard/WidgetType.h +++ /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 - -namespace frc { - -/** - * Represents the type of a widget in Shuffleboard. Using this is preferred over - * specifying raw strings, to avoid typos and having to know or look up the - * exact string name for a desired widget. - * - * @see BuiltInWidgets the built-in widget types - */ -class WidgetType { - public: - explicit constexpr WidgetType(const char* widgetName) - : m_widgetName(widgetName) {} - ~WidgetType() = default; - - /** - * Gets the string type of the widget as defined by that widget in - * Shuffleboard. - */ - std::string_view GetWidgetName() const; - - private: - const char* m_widgetName; -}; - -} // namespace frc diff --git a/wpilibc/src/test/native/cpp/shuffleboard/MockActuatorSendable.cpp b/wpilibc/src/test/native/cpp/shuffleboard/MockActuatorSendable.cpp deleted file mode 100644 index 5a9f9938b1c..00000000000 --- a/wpilibc/src/test/native/cpp/shuffleboard/MockActuatorSendable.cpp +++ /dev/null @@ -1,16 +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. - -#include "shuffleboard/MockActuatorSendable.h" - -#include -#include - -MockActuatorSendable::MockActuatorSendable(std::string_view name) { - wpi::SendableRegistry::Add(this, name); -} - -void MockActuatorSendable::InitSendable(wpi::SendableBuilder& builder) { - builder.SetActuator(true); -} diff --git a/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp deleted file mode 100644 index 6354713d5d4..00000000000 --- a/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardInstanceTest.cpp +++ /dev/null @@ -1,130 +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. - -#include "frc/shuffleboard/ShuffleboardInstance.h" // NOLINT(build/include_order) - -#include - -#include -#include -#include -#include - -#include "shuffleboard/MockActuatorSendable.h" - -class NTWrapper { - public: - NTWrapper() { inst = nt::NetworkTableInstance::Create(); } - - ~NTWrapper() { nt::NetworkTableInstance::Destroy(inst); } - - nt::NetworkTableInstance inst; -}; - -TEST(ShuffleboardInstanceTest, PathFluent) { - NTWrapper ntInst; - frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst}; - - auto entry = shuffleboardInst.GetTab("Tab Title") - .GetLayout("List", "List Layout") - .Add("Data", "string") - .WithWidget("Text View") - .GetEntry(); - - EXPECT_EQ("string", entry->GetString("")) << "Wrong entry value"; - EXPECT_EQ("/Shuffleboard/Tab Title/List/Data", entry->GetTopic().GetName()) - << "Entry path generated incorrectly"; -} - -TEST(ShuffleboardInstanceTest, NestedLayoutsFluent) { - NTWrapper ntInst; - frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst}; - - auto entry = shuffleboardInst.GetTab("Tab") - .GetLayout("First", "List") - .GetLayout("Second", "List") - .GetLayout("Third", "List") - .GetLayout("Fourth", "List") - .Add("Value", "string") - .GetEntry(); - - EXPECT_EQ("string", entry->GetString("")) << "Wrong entry value"; - EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value", - entry->GetTopic().GetName()) - << "Entry path generated incorrectly"; -} - -TEST(ShuffleboardInstanceTest, NestedLayoutsOop) { - NTWrapper ntInst; - frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst}; - - frc::ShuffleboardTab& tab = shuffleboardInst.GetTab("Tab"); - frc::ShuffleboardLayout& first = tab.GetLayout("First", "List"); - frc::ShuffleboardLayout& second = first.GetLayout("Second", "List"); - frc::ShuffleboardLayout& third = second.GetLayout("Third", "List"); - frc::ShuffleboardLayout& fourth = third.GetLayout("Fourth", "List"); - frc::SimpleWidget& widget = fourth.Add("Value", "string"); - auto entry = widget.GetEntry(); - - EXPECT_EQ("string", entry->GetString("")) << "Wrong entry value"; - EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value", - entry->GetTopic().GetName()) - << "Entry path generated incorrectly"; -} - -TEST(ShuffleboardInstanceTest, LayoutTypeIsSet) { - NTWrapper ntInst; - frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst}; - - std::string_view layoutType = "Type"; - shuffleboardInst.GetTab("Tab").GetLayout("Title", layoutType); - shuffleboardInst.Update(); - auto entry = ntInst.inst.GetEntry( - "/Shuffleboard/.metadata/Tab/Title/PreferredComponent"); - EXPECT_EQ(layoutType, entry.GetString("Not Set")) << "Layout type not set"; -} - -TEST(ShuffleboardInstanceTest, NestedActuatorWidgetsAreDisabled) { - NTWrapper ntInst; - frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst}; - - MockActuatorSendable sendable("Actuator"); - shuffleboardInst.GetTab("Tab").GetLayout("Title", "Layout").Add(sendable); - auto controllableEntry = - ntInst.inst.GetEntry("/Shuffleboard/Tab/Title/Actuator/.controllable"); - shuffleboardInst.Update(); - - // Note: we use the unsafe `GetBoolean()` method because if the value is NOT - // a boolean, or if it is not present, then something has clearly gone very, - // very wrong - bool controllable = controllableEntry.GetValue().GetBoolean(); - // Sanity check - EXPECT_TRUE(controllable) - << "The nested actuator widget should be enabled by default"; - shuffleboardInst.DisableActuatorWidgets(); - controllable = controllableEntry.GetValue().GetBoolean(); - EXPECT_FALSE(controllable) - << "The nested actuator widget should have been disabled"; -} - -TEST(ShuffleboardInstanceTest, DuplicateSelectTabs) { - NTWrapper ntInst; - frc::detail::ShuffleboardInstance shuffleboardInst{ntInst.inst}; - std::atomic_int counter = 0; - auto subscriber = - ntInst.inst.GetStringTopic("/Shuffleboard/.metadata/Selected") - .Subscribe("", {.keepDuplicates = true}); - ntInst.inst.AddListener( - subscriber, nt::EventFlags::kValueAll | nt::EventFlags::kImmediate, - [&counter](auto& event) { counter++; }); - - // There shouldn't be anything there - EXPECT_EQ(0, counter); - - shuffleboardInst.SelectTab("tab1"); - shuffleboardInst.SelectTab("tab1"); - EXPECT_TRUE(ntInst.inst.WaitForListenerQueue(1.0)) - << "Listener queue timed out!"; - EXPECT_EQ(2, counter); -} diff --git a/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardTest.cpp b/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardTest.cpp deleted file mode 100644 index db689db4cea..00000000000 --- a/wpilibc/src/test/native/cpp/shuffleboard/ShuffleboardTest.cpp +++ /dev/null @@ -1,13 +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. - -#include - -#include "frc/shuffleboard/Shuffleboard.h" - -TEST(ShuffleboardTest, TabObjectsCached) { - auto& tab1 = frc::Shuffleboard::GetTab("testTabObjectsCached"); - auto& tab2 = frc::Shuffleboard::GetTab("testTabObjectsCached"); - EXPECT_EQ(&tab1, &tab2) << "Tab objects were not cached"; -} diff --git a/wpilibc/src/test/native/cpp/shuffleboard/SuppliedValueWidgetTest.cpp b/wpilibc/src/test/native/cpp/shuffleboard/SuppliedValueWidgetTest.cpp deleted file mode 100644 index 91c68db79aa..00000000000 --- a/wpilibc/src/test/native/cpp/shuffleboard/SuppliedValueWidgetTest.cpp +++ /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. - -#include -#include - -#include -#include -#include - -#include "frc/shuffleboard/ShuffleboardInstance.h" -#include "frc/shuffleboard/ShuffleboardTab.h" - -using namespace frc; - -class NTWrapper { - public: - NTWrapper() { inst = nt::NetworkTableInstance::Create(); } - - ~NTWrapper() { nt::NetworkTableInstance::Destroy(inst); } - - nt::NetworkTableInstance inst; -}; - -class SuppliedValueWidgetTest : public testing::Test { - protected: - NTWrapper m_ntInst; - frc::detail::ShuffleboardInstance m_shuffleboardInst{m_ntInst.inst}; - frc::ShuffleboardTab* m_tab = &(m_shuffleboardInst.GetTab("Tab")); -}; - -TEST_F(SuppliedValueWidgetTest, AddString) { - std::string str = "foo"; - m_tab->AddString("String", [&str]() { return str; }); - auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/String"); - - m_shuffleboardInst.Update(); - EXPECT_EQ("foo", entry.GetValue().GetString()); -} - -TEST_F(SuppliedValueWidgetTest, AddNumber) { - int num = 0; - m_tab->AddNumber("Num", [&num]() { return ++num; }); - auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Num"); - - m_shuffleboardInst.Update(); - EXPECT_FLOAT_EQ(1.0, entry.GetValue().GetDouble()); -} - -TEST_F(SuppliedValueWidgetTest, AddBoolean) { - bool value = true; - m_tab->AddBoolean("Bool", [&value]() { return value; }); - auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Bool"); - - m_shuffleboardInst.Update(); - EXPECT_EQ(true, entry.GetValue().GetBoolean()); -} - -TEST_F(SuppliedValueWidgetTest, AddStringArray) { - std::vector strings = {"foo", "bar"}; - m_tab->AddStringArray("Strings", [&strings]() { return strings; }); - auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Strings"); - - m_shuffleboardInst.Update(); - auto actual = entry.GetValue().GetStringArray(); - - EXPECT_EQ(strings.size(), actual.size()); - for (size_t i = 0; i < strings.size(); i++) { - EXPECT_EQ(strings[i], actual[i]); - } -} - -TEST_F(SuppliedValueWidgetTest, AddNumberArray) { - std::vector nums = {0, 1, 2, 3}; - m_tab->AddNumberArray("Numbers", [&nums]() { return nums; }); - auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Numbers"); - - m_shuffleboardInst.Update(); - auto actual = entry.GetValue().GetDoubleArray(); - - EXPECT_EQ(nums.size(), actual.size()); - for (size_t i = 0; i < nums.size(); i++) { - EXPECT_FLOAT_EQ(nums[i], actual[i]); - } -} - -TEST_F(SuppliedValueWidgetTest, AddBooleanArray) { - std::vector bools = {true, false}; - m_tab->AddBooleanArray("Booleans", [&bools]() { return bools; }); - auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Booleans"); - - m_shuffleboardInst.Update(); - auto actual = entry.GetValue().GetBooleanArray(); - - EXPECT_EQ(bools.size(), actual.size()); - for (size_t i = 0; i < bools.size(); i++) { - EXPECT_FLOAT_EQ(bools[i], actual[i]); - } -} - -TEST_F(SuppliedValueWidgetTest, AddRaw) { - std::vector bytes = {1, 2, 3}; - m_tab->AddRaw("Raw", [&bytes]() { return bytes; }); - auto entry = m_ntInst.inst.GetEntry("/Shuffleboard/Tab/Raw"); - - m_shuffleboardInst.Update(); - auto actual = entry.GetValue().GetRaw(); - EXPECT_EQ(bytes, std::vector(actual.begin(), actual.end())); -} diff --git a/wpilibc/src/test/native/include/shuffleboard/MockActuatorSendable.h b/wpilibc/src/test/native/include/shuffleboard/MockActuatorSendable.h deleted file mode 100644 index 8baf2a2db4c..00000000000 --- a/wpilibc/src/test/native/include/shuffleboard/MockActuatorSendable.h +++ /dev/null @@ -1,19 +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 - -/** - * A mock sendable that marks itself as an actuator. - */ -class MockActuatorSendable : public wpi::Sendable { - public: - explicit MockActuatorSendable(std::string_view name); - - void InitSendable(wpi::SendableBuilder& builder) override; -}; diff --git a/wpilibcExamples/src/main/cpp/examples/HatchbotInlined/cpp/RobotContainer.cpp b/wpilibcExamples/src/main/cpp/examples/HatchbotInlined/cpp/RobotContainer.cpp index 76714d86813..04342cd9b6e 100644 --- a/wpilibcExamples/src/main/cpp/examples/HatchbotInlined/cpp/RobotContainer.cpp +++ b/wpilibcExamples/src/main/cpp/examples/HatchbotInlined/cpp/RobotContainer.cpp @@ -4,7 +4,7 @@ #include "RobotContainer.h" -#include +#include RobotContainer::RobotContainer() { // Initialize all of your commands and subsystems here @@ -15,36 +15,10 @@ RobotContainer::RobotContainer() { m_chooser.AddOption("Complex Auto", m_complexAuto.get()); // Put the chooser on the dashboard - frc::Shuffleboard::GetTab("Autonomous").Add(m_chooser); + frc::SmartDashboard::PutData("Autonomous", &m_chooser); // Put subsystems to dashboard. - frc::Shuffleboard::GetTab("Drivetrain").Add(m_drive); - frc::Shuffleboard::GetTab("HatchSubsystem").Add(m_hatch); - - // Log Shuffleboard events for command initialize, execute, finish, interrupt - frc2::CommandScheduler::GetInstance().OnCommandInitialize( - [](const frc2::Command& command) { - frc::Shuffleboard::AddEventMarker( - "Command initialized", command.GetName(), - frc::ShuffleboardEventImportance::kNormal); - }); - frc2::CommandScheduler::GetInstance().OnCommandExecute( - [](const frc2::Command& command) { - frc::Shuffleboard::AddEventMarker( - "Command executed", command.GetName(), - frc::ShuffleboardEventImportance::kNormal); - }); - frc2::CommandScheduler::GetInstance().OnCommandFinish( - [](const frc2::Command& command) { - frc::Shuffleboard::AddEventMarker( - "Command finished", command.GetName(), - frc::ShuffleboardEventImportance::kNormal); - }); - frc2::CommandScheduler::GetInstance().OnCommandInterrupt( - [](const frc2::Command& command) { - frc::Shuffleboard::AddEventMarker( - "Command interrupted", command.GetName(), - frc::ShuffleboardEventImportance::kNormal); - }); + frc::SmartDashboard::PutData("Drivetrain", &m_drive); + frc::SmartDashboard::PutData("HatchSubsystem", &m_hatch); // Configure the button bindings ConfigureButtonBindings(); diff --git a/wpilibcExamples/src/main/cpp/examples/HatchbotTraditional/cpp/RobotContainer.cpp b/wpilibcExamples/src/main/cpp/examples/HatchbotTraditional/cpp/RobotContainer.cpp index faf9d1f02e8..f87ab6d75b9 100644 --- a/wpilibcExamples/src/main/cpp/examples/HatchbotTraditional/cpp/RobotContainer.cpp +++ b/wpilibcExamples/src/main/cpp/examples/HatchbotTraditional/cpp/RobotContainer.cpp @@ -4,7 +4,7 @@ #include "RobotContainer.h" -#include +#include #include #include "commands/DefaultDrive.h" @@ -20,36 +20,10 @@ RobotContainer::RobotContainer() { m_chooser.AddOption("Complex Auto", &m_complexAuto); // Put the chooser on the dashboard - frc::Shuffleboard::GetTab("Autonomous").Add(m_chooser); + frc::SmartDashboard::PutData("Autonomous", &m_chooser); // Put subsystems to dashboard. - frc::Shuffleboard::GetTab("Drivetrain").Add(m_drive); - frc::Shuffleboard::GetTab("HatchSubsystem").Add(m_hatch); - - // Log Shuffleboard events for command initialize, execute, finish, interrupt - frc2::CommandScheduler::GetInstance().OnCommandInitialize( - [](const frc2::Command& command) { - frc::Shuffleboard::AddEventMarker( - "Command initialized", command.GetName(), - frc::ShuffleboardEventImportance::kNormal); - }); - frc2::CommandScheduler::GetInstance().OnCommandExecute( - [](const frc2::Command& command) { - frc::Shuffleboard::AddEventMarker( - "Command executed", command.GetName(), - frc::ShuffleboardEventImportance::kNormal); - }); - frc2::CommandScheduler::GetInstance().OnCommandFinish( - [](const frc2::Command& command) { - frc::Shuffleboard::AddEventMarker( - "Command finished", command.GetName(), - frc::ShuffleboardEventImportance::kNormal); - }); - frc2::CommandScheduler::GetInstance().OnCommandInterrupt( - [](const frc2::Command& command) { - frc::Shuffleboard::AddEventMarker( - "Command interrupted", command.GetName(), - frc::ShuffleboardEventImportance::kNormal); - }); + frc::SmartDashboard::PutData("Drivetrain", &m_drive); + frc::SmartDashboard::PutData("HatchSubsystem", &m_hatch); // Configure the button bindings ConfigureButtonBindings(); diff --git a/wpilibcExamples/src/main/cpp/examples/MecanumControllerCommand/cpp/RobotContainer.cpp b/wpilibcExamples/src/main/cpp/examples/MecanumControllerCommand/cpp/RobotContainer.cpp index 0d3db36cb04..427da554018 100644 --- a/wpilibcExamples/src/main/cpp/examples/MecanumControllerCommand/cpp/RobotContainer.cpp +++ b/wpilibcExamples/src/main/cpp/examples/MecanumControllerCommand/cpp/RobotContainer.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff --git a/wpilibcExamples/src/main/cpp/examples/ShuffleBoard/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/examples/ShuffleBoard/cpp/Robot.cpp deleted file mode 100644 index 61c5dd44964..00000000000 --- a/wpilibcExamples/src/main/cpp/examples/ShuffleBoard/cpp/Robot.cpp +++ /dev/null @@ -1,88 +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. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * This sample program provides an example for ShuffleBoard, an alternative - * to SmartDashboard for displaying values and properties of different robot - * parts. - * - * ShuffleBoard can use pre-programmed widgets to display various values, such - * as Boolean Boxes, Sliders, Graphs, and more. In addition, they can display - * things in various Tabs. - * - * For more information on how to create personal layouts and more in - * ShuffleBoard, feel free to reference the official FIRST WPILib documentation - * online. - */ -class Robot : public frc::TimedRobot { - public: - Robot() { - wpi::SendableRegistry::AddChild(&m_robotDrive, &m_left); - wpi::SendableRegistry::AddChild(&m_robotDrive, &m_right); - - // Add a widget titled 'Max Speed' with a number slider. - m_maxSpeed = frc::Shuffleboard::GetTab("Configuration") - .Add("Max Speed", 1) - .WithWidget("Number Slider") - .GetEntry(); - - // Create a 'DriveBase' tab and add the drivetrain object to it. - frc::ShuffleboardTab& driveBaseTab = frc::Shuffleboard::GetTab("DriveBase"); - driveBaseTab.Add("TankDrive", m_robotDrive); - - // Put encoders in a list layout. - frc::ShuffleboardLayout& encoders = - driveBaseTab.GetLayout("Encoders", frc::BuiltInLayouts::kList) - .WithPosition(0, 0) - .WithSize(2, 2); - encoders.Add("Left Encoder", m_leftEncoder); - encoders.Add("Right Encoder", m_rightEncoder); - - // Create a 'Elevator' tab and add the potentiometer and elevator motor to - // it. - frc::ShuffleboardTab& elevatorTab = frc::Shuffleboard::GetTab("Elevator"); - elevatorTab.Add("Motor", m_elevatorMotor); - elevatorTab.Add("Potentiometer", m_ElevatorPot); - } - - void AutonomousInit() override { - // Update the Max Output for the drivetrain. - m_robotDrive.SetMaxOutput(m_maxSpeed->GetDouble(1.0)); - } - - private: - frc::PWMSparkMax m_left{0}; - frc::PWMSparkMax m_right{1}; - frc::PWMSparkMax m_elevatorMotor{2}; - - frc::DifferentialDrive m_robotDrive{ - [&](double output) { m_left.Set(output); }, - [&](double output) { m_right.Set(output); }}; - - frc::Joystick m_stick{0}; - - frc::Encoder m_leftEncoder{0, 1}; - frc::Encoder m_rightEncoder{2, 3}; - frc::AnalogPotentiometer m_ElevatorPot{0}; - - nt::GenericEntry* m_maxSpeed; -}; - -#ifndef RUNNING_FRC_TESTS -int main() { - return frc::StartRobot(); -} -#endif diff --git a/wpilibcExamples/src/main/cpp/examples/Solenoid/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/examples/Solenoid/cpp/Robot.cpp index 25311e82d68..e4b51c9e3a7 100644 --- a/wpilibcExamples/src/main/cpp/examples/Solenoid/cpp/Robot.cpp +++ b/wpilibcExamples/src/main/cpp/examples/Solenoid/cpp/Robot.cpp @@ -4,41 +4,35 @@ #include "Robot.h" -#include +#include #include Robot::Robot() { // Publish elements to shuffleboard. - frc::ShuffleboardTab& tab = frc::Shuffleboard::GetTab("Pneumatics"); - tab.Add("Single Solenoid", m_solenoid); - tab.Add("Double Solenoid", m_doubleSolenoid); - tab.Add("Compressor", m_compressor); - - // Also publish some raw data - tab.AddDouble("PH Pressure [PSI]", [&] { - // Get the pressure (in PSI) from the analog sensor connected to the PH. - // This function is supported only on the PH! - // On a PCM, this function will return 0. - units::pounds_per_square_inch_t pressure = m_compressor.GetPressure(); - return pressure.value(); - }); - tab.AddDouble("Compressor Current", [&] { - // Get compressor current draw. - units::ampere_t compressorCurrent = m_compressor.GetCurrent(); - return compressorCurrent.value(); - }); - tab.AddBoolean("Compressor Active", [&] { - // Get whether the compressor is active. - return m_compressor.IsEnabled(); - }); - tab.AddBoolean("Pressure Switch", [&] { - // Get the digital pressure switch connected to the PCM/PH. - // The switch is open when the pressure is over ~120 PSI. - return m_compressor.GetPressureSwitchValue(); - }); + frc::SmartDashboard::PutData("Single Solenoid", &m_solenoid); + frc::SmartDashboard::PutData("Double Solenoid", &m_doubleSolenoid); + frc::SmartDashboard::PutData("Compressor", &m_compressor); } void Robot::TeleopPeriodic() { + // Publish some raw data + + // Get the pressure (in PSI) from the analog sensor connected to the PH. + // This function is supported only on the PH! + // On a PCM, this function will return 0. + frc::SmartDashboard::PutNumber("PH Pressure [PSI]", + m_compressor.GetPressure().value()); + // Get compressor current draw. + frc::SmartDashboard::PutNumber("Compressor Current", + m_compressor.GetCurrent().value()); + // Get whether the compressor is active. + frc::SmartDashboard::PutBoolean("Compressor Active", + m_compressor.IsEnabled()); + // Get the digital pressure switch connected to the PCM/PH. + // The switch is open when the pressure is over ~120 PSI. + frc::SmartDashboard::PutBoolean("Pressure Switch", + m_compressor.GetPressureSwitchValue()); + /* * The output of GetRawButton is true/false depending on whether * the button is pressed; Set takes a boolean for whether diff --git a/wpilibcExamples/src/main/cpp/examples/SwerveControllerCommand/cpp/RobotContainer.cpp b/wpilibcExamples/src/main/cpp/examples/SwerveControllerCommand/cpp/RobotContainer.cpp index 6c8de057532..8cdada50d5b 100644 --- a/wpilibcExamples/src/main/cpp/examples/SwerveControllerCommand/cpp/RobotContainer.cpp +++ b/wpilibcExamples/src/main/cpp/examples/SwerveControllerCommand/cpp/RobotContainer.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff --git a/wpilibcExamples/src/main/cpp/examples/Ultrasonic/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/examples/Ultrasonic/cpp/Robot.cpp index 67c5b719b01..fda7fcd00d6 100644 --- a/wpilibcExamples/src/main/cpp/examples/Ultrasonic/cpp/Robot.cpp +++ b/wpilibcExamples/src/main/cpp/examples/Ultrasonic/cpp/Robot.cpp @@ -4,14 +4,13 @@ #include "Robot.h" -#include #include #include Robot::Robot() { // Add the ultrasonic on the "Sensors" tab of the dashboard // Data will update automatically - frc::Shuffleboard::GetTab("Sensors").Add(m_rangeFinder); + frc::SmartDashboard::PutData("Sensors", &m_rangeFinder); } void Robot::TeleopPeriodic() { diff --git a/wpilibcExamples/src/main/cpp/examples/examples.json b/wpilibcExamples/src/main/cpp/examples/examples.json index c20ec3d1a45..d4a93ca9dcf 100644 --- a/wpilibcExamples/src/main/cpp/examples/examples.json +++ b/wpilibcExamples/src/main/cpp/examples/examples.json @@ -46,7 +46,6 @@ "tags": [ "Hardware", "Joystick", - "Shuffleboard", "Pneumatics" ], "foldername": "Solenoid", @@ -119,8 +118,7 @@ "tags": [ "Hardware", "Ultrasonic", - "SmartDashboard", - "Shuffleboard" + "SmartDashboard" ], "foldername": "Ultrasonic", "gradlebase": "cpp", @@ -318,21 +316,6 @@ "gradlebase": "c", "commandversion": 2 }, - { - "name": "Shuffleboard", - "description": "Present various data via the Shuffleboard API.", - "tags": [ - "Basic Robot", - "Differential Drive", - "Elevator", - "Analog", - "Encoder", - "Shuffleboard" - ], - "foldername": "ShuffleBoard", - "gradlebase": "cpp", - "commandversion": 2 - }, { "name": "'Traditional' Hatchbot", "description": "A fully-functional command-based hatchbot for the 2019 game, written in the 'traditional' style, i.e. commands are given their own classes.", @@ -341,7 +324,6 @@ "Command-based", "Differential Drive", "Encoder", - "Shuffleboard", "Sendable", "DataLog", "Pneumatics", @@ -359,7 +341,6 @@ "Command-based", "Differential Drive", "Encoder", - "Shuffleboard", "Sendable", "DataLog", "Pneumatics", diff --git a/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp index 850e2e41800..50dbd4eeeb7 100644 --- a/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp +++ b/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -47,7 +46,6 @@ void Robot::StartCompetition() { } } else if (IsTest()) { frc::LiveWindow::SetEnabled(true); - frc::Shuffleboard::EnableActuatorWidgets(); modeThread.InTest(true); Test(); modeThread.InTest(false); @@ -55,7 +53,6 @@ void Robot::StartCompetition() { wpi::WaitForObject(event.GetHandle()); } frc::LiveWindow::SetEnabled(false); - frc::Shuffleboard::DisableActuatorWidgets(); } else { modeThread.InTeleop(true); Teleop(); diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/IterativeRobotBase.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/IterativeRobotBase.java index b0c46604283..ed4d9de959f 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/IterativeRobotBase.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/IterativeRobotBase.java @@ -10,7 +10,6 @@ import edu.wpi.first.hal.HAL; import edu.wpi.first.networktables.NetworkTableInstance; import edu.wpi.first.wpilibj.livewindow.LiveWindow; -import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import java.util.ConcurrentModificationException; @@ -331,7 +330,6 @@ protected void loopFunc() { case kTest -> { if (m_lwEnabledInTest) { LiveWindow.setEnabled(false); - Shuffleboard.disableActuatorWidgets(); } testExit(); } @@ -357,7 +355,6 @@ protected void loopFunc() { case kTest -> { if (m_lwEnabledInTest) { LiveWindow.setEnabled(true); - Shuffleboard.enableActuatorWidgets(); } testInit(); m_watchdog.addEpoch("testInit()"); @@ -404,8 +401,6 @@ protected void loopFunc() { m_watchdog.addEpoch("SmartDashboard.updateValues()"); LiveWindow.updateValues(); m_watchdog.addEpoch("LiveWindow.updateValues()"); - Shuffleboard.update(); - m_watchdog.addEpoch("Shuffleboard.update()"); if (isSimulation()) { HAL.simPeriodicBefore(); diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java index e595a5899e6..775562e293c 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java @@ -18,7 +18,6 @@ import edu.wpi.first.networktables.NetworkTableInstance; import edu.wpi.first.util.WPIUtilJNI; import edu.wpi.first.wpilibj.livewindow.LiveWindow; -import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; import edu.wpi.first.wpilibj.util.WPILibVersion; import java.io.File; import java.io.IOException; @@ -227,7 +226,6 @@ protected RobotBase() { }); LiveWindow.setEnabled(false); - Shuffleboard.disableActuatorWidgets(); } /** diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/BuiltInLayouts.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/BuiltInLayouts.java deleted file mode 100644 index fb642ae6ab7..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/BuiltInLayouts.java +++ /dev/null @@ -1,61 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -/** - * The types of layouts bundled with Shuffleboard. - * - *

{@code
- * ShuffleboardLayout myList = Shuffleboard.getTab("My Tab")
- *   .getLayout(BuiltinLayouts.kList, "My List");
- * }
- */ -public enum BuiltInLayouts implements LayoutType { - /** - * Groups components in a vertical list. New widgets added to the layout will be placed at the - * bottom of the list.
- * Custom properties: - * - * - * - * - * - *
NameTypeDefault ValueNotes
Label positionString"BOTTOM"The position of component labels inside the grid. One of - * {@code ["TOP", "LEFT", "BOTTOM", "RIGHT", "HIDDEN"}
- */ - kList("List Layout"), - - /** - * Groups components in an n x m grid. Grid layouts default to 3x3.
- * Custom properties: - * - * - * - * - * - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
Number of columnsNumber3Must be in the range [1,15]
Number of rowsNumber3Must be in the range [1,15]
Label positionString"BOTTOM"The position of component labels inside the grid. - * One of {@code ["TOP", "LEFT", "BOTTOM", "RIGHT", "HIDDEN"}
- */ - kGrid("Grid Layout"), - ; - - private final String m_layoutName; - - BuiltInLayouts(String layoutName) { - m_layoutName = layoutName; - } - - @Override - public String getLayoutName() { - return m_layoutName; - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/BuiltInWidgets.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/BuiltInWidgets.java deleted file mode 100644 index 47c6cf821f9..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/BuiltInWidgets.java +++ /dev/null @@ -1,476 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -/** - * The types of the widgets bundled with Shuffleboard. - * - *

For example, setting a number to be displayed with a slider: - * - *

{@code
- * GenericEntry example = Shuffleboard.getTab("My Tab")
- *   .add("My Number", 0)
- *   .withWidget(BuiltInWidgets.kNumberSlider)
- *   .withProperties(Map.of("min", 0, "max", 1))
- *   .getEntry();
- * }
- * - *

Each value in this enum goes into detail on what data types that widget can support, as well - * as the custom properties that widget uses. - */ -public enum BuiltInWidgets implements WidgetType { - /** - * Displays a value with a simple text field.
- * Supported types: - * - *

    - *
  • String - *
  • Number - *
  • Boolean - *
- * - *
- * This widget has no custom properties. - */ - kTextView("Text View"), - /** - * Displays a number with a controllable slider.
- * Supported types: - * - *
    - *
  • Number - *
- * - *
- * Custom properties: - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
MinNumber-1.0The minimum value of the slider
MaxNumber1.0The maximum value of the slider
Block incrementNumber0.0625How much to move the slider by with the arrow keys
- */ - kNumberSlider("Number Slider"), - /** - * Displays a number with a view-only bar.
- * Supported types: - * - *
    - *
  • Number - *
- * - *
- * Custom properties: - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
MinNumber-1.0The minimum value of the bar
MaxNumber1.0The maximum value of the bar
CenterNumber0The center ("zero") value of the bar
- */ - kNumberBar("Number Bar"), - /** - * Displays a number with a view-only dial. Displayed values are rounded to the nearest integer. - *
- * Supported types: - * - *
    - *
  • Number - *
- * - *
- * Custom properties: - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
MinNumber0The minimum value of the dial
MaxNumber100The maximum value of the dial
Show valueBooleantrueWhether or not to show the value as text
- */ - kDial("Simple Dial"), - /** - * Displays a number with a graph. NOTE: graphs can be taxing on the computer - * running the dashboard. Keep the number of visible data points to a minimum. Making the widget - * smaller also helps with performance, but may cause the graph to become difficult to read.
- * Supported types: - * - *
    - *
  • Number - *
  • Number array - *
- * - *
- * Custom properties: - * - * - * - * - * - *
NameTypeDefault ValueNotes
Visible timeNumber30How long, in seconds, should past data be visible for
- */ - kGraph("Graph"), - /** - * Displays a boolean value as a large colored box.
- * Supported types: - * - *
    - *
  • Boolean - *
- * - *
- * Custom properties: - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
Color when trueColor"green"Can be specified as a string ({@code "#00FF00"}) or a rgba integer ({@code 0x00FF0000}) - *
Color when falseColor"red"Can be specified as a string or a number
- */ - kBooleanBox("Boolean Box"), - /** - * Displays a boolean with a large interactive toggle button.
- * Supported types: - * - *
    - *
  • Boolean - *
- * - *
- * This widget has no custom properties. - */ - kToggleButton("Toggle Button"), - /** - * Displays a boolean with a fixed-size toggle switch.
- * Supported types: - * - *
    - *
  • Boolean - *
- * - *
- * This widget has no custom properties. - */ - kToggleSwitch("Toggle Switch"), - /** - * Displays an analog input or a raw number with a number bar.
- * Supported types: - * - *
    - *
  • Number - *
  • {@link edu.wpi.first.wpilibj.AnalogInput} - *
- * - *
- * Custom properties: - * - * - * - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
MinNumber0The minimum value of the bar
MaxNumber5The maximum value of the bar
CenterNumber0The center ("zero") value of the bar
OrientationString"HORIZONTAL"The orientation of the bar. One of {@code ["HORIZONTAL", "VERTICAL"]}
Number of tick marksNumber5The number of discrete ticks on the bar
- */ - kVoltageView("Voltage View"), - /** - * Displays a {@link edu.wpi.first.wpilibj.PowerDistribution PowerDistribution}.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj.PowerDistribution} - *
- * - *
- * Custom properties: - * - * - * - * - * - *
NameTypeDefault ValueNotes
Show voltage and current valuesBooleantrueWhether or not to display the voltage and current draw
- */ - kPowerDistribution("PDP"), - /** - * Displays a {@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser SendableChooser} with a - * dropdown combo box with a list of options.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser} - *
- * - *
- * This widget has no custom properties. - */ - kComboBoxChooser("ComboBox Chooser"), - /** - * Displays a {@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser SendableChooser} with a - * toggle button for each available option.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj.smartdashboard.SendableChooser} - *
- * - *
- * This widget has no custom properties. - */ - kSplitButtonChooser("Split Button Chooser"), - /** - * Displays an {@link edu.wpi.first.wpilibj.Encoder} displaying its speed, total traveled - * distance, and its distance per tick.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj.Encoder} - *
- * - *
- * This widget has no custom properties. - */ - kEncoder("Encoder"), - /** - * Displays a {@link edu.wpi.first.wpilibj.motorcontrol.MotorController MotorController}. The - * motor controller will be controllable from the dashboard when test mode is enabled, but will - * otherwise be view-only.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.PWMMotorController} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.DMC60} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.Jaguar} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.PWMTalonFX} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.PWMTalonSRX} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.PWMVenom} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.PWMVictorSPX} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.SD540} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.Spark} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.Talon} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.Victor} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.VictorSP} - *
  • {@link edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup} - *
  • Any custom subclass of {@code MotorController} - *
- * - *
- * Custom properties: - * - * - * - * - * - *
NameTypeDefault ValueNotes
OrientationString"HORIZONTAL"One of {@code ["HORIZONTAL", "VERTICAL"]}
- */ - kMotorController("Motor Controller"), - /** - * Displays a command with a toggle button. Pressing the button will start the command, and the - * button will automatically release when the command completes.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj2.command.Command} - *
  • Any custom subclass of {@code Command} - *
- * - *
- * This widget has no custom properties. - */ - kCommand("Command"), - /** - * Displays a PID command with a checkbox and an editor for the PIDF constants. Selecting the - * checkbox will start the command, and the checkbox will automatically deselect when the command - * completes.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj2.command.PIDCommand} - *
  • Any custom subclass of {@code PIDCommand} - *
- * - *
- * This widget has no custom properties. - */ - kPIDCommand("PID Command"), - /** - * Displays a PID controller with an editor for the PIDF constants and a toggle switch for - * enabling and disabling the controller.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.math.controller.PIDController} - *
- * - *
- * This widget has no custom properties. - */ - kPIDController("PID Controller"), - /** - * Displays an accelerometer with a number bar displaying the magnitude of the acceleration and - * text displaying the exact value.
- * Custom properties: - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
MinNumber-1The minimum acceleration value to display
MaxNumber1The maximum acceleration value to display
Show textBooleantrueShow or hide the acceleration values
PrecisionNumber2How many numbers to display after the decimal point
Show tick marksBooleanfalseShow or hide the tick marks on the number bars
- */ - kAccelerometer("Accelerometer"), - /** - * Displays a 3-axis accelerometer with a number bar for each axis' acceleration.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj.ADXL345_I2C} - *
- * - *
- * Custom properties: - * - * - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
Show valueBooleantrueShow or hide the acceleration values
PrecisionNumber2How many numbers to display after the decimal point
Show tick marksBooleanfalseShow or hide the tick marks on the number bars
- */ - k3AxisAccelerometer("3-Axis Accelerometer"), - /** - * Displays a gyro with a dial from 0 to 360 degrees.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj.AnalogGyro} - *
  • Any custom subclass of {@code GyroBase} (such as a MXP gyro) - *
- * - *
- * Custom properties: - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
Major tick spacingNumber45Degrees
Starting angleNumber180How far to rotate the entire dial, in degrees
Show tick mark ringBooleantrue
- */ - kGyro("Gyro"), - /** - * Displays a relay with toggle buttons for each supported mode (off, on, forward, reverse).
- * This widget has no custom properties. - */ - kRelay("Relay"), - /** - * Displays a differential drive with a widget that displays the speed of each side of the - * drivebase and a vector for the direction and rotation of the drivebase. The widget will be - * controllable if the robot is in test mode.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj.drive.DifferentialDrive} - *
- * - *
- * Custom properties: - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
Number of wheelsNumber4Must be a positive even integer - *
Wheel diameterNumber80Pixels
Show velocity vectorsBooleantrue
- */ - kDifferentialDrive("Differential Drivebase"), - /** - * Displays a mecanum drive with a widget that displays the speed of each wheel, and vectors for - * the direction and rotation of the drivebase. The widget will be controllable if the robot is in - * test mode.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj.drive.MecanumDrive} - *
- * - *
- * Custom properties: - * - * - * - * - *
NameTypeDefault ValueNotes
Show velocity vectorsBooleantrue
- */ - kMecanumDrive("Mecanum Drivebase"), - /** - * Displays a camera stream.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.cscore.VideoSource} (as long as it is streaming on an MJPEG server) - *
- * - *
- * Custom properties: - * - * - * - * - * - * - * - * - * - * - *
NameTypeDefault ValueNotes
Show crosshairBooleantrueShow or hide a crosshair on the image
Crosshair colorColor"white"Can be a string or a rgba integer
Show controlsBooleantrueShow or hide the stream controls - *
RotationString"NONE"Rotates the displayed image. One of {@code ["NONE", "QUARTER_CW", "QUARTER_CCW", "HALF"]} - *
- */ - kCameraStream("Camera Stream"), - /** - * Displays a Field2d object.
- * Supported types: - * - *
    - *
  • {@link edu.wpi.first.wpilibj.smartdashboard.Field2d} - *
- */ - kField("Field"), - ; - - private final String m_widgetName; - - BuiltInWidgets(String widgetName) { - this.m_widgetName = widgetName; - } - - @Override - public String getWidgetName() { - return m_widgetName; - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ComplexWidget.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ComplexWidget.java deleted file mode 100644 index cef9c0733f1..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ComplexWidget.java +++ /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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import edu.wpi.first.networktables.NetworkTable; -import edu.wpi.first.util.sendable.Sendable; -import edu.wpi.first.wpilibj.smartdashboard.SendableBuilderImpl; - -/** - * A Shuffleboard widget that handles a {@link Sendable} object such as a motor controller or - * sensor. - */ -public final class ComplexWidget extends ShuffleboardWidget { - private final Sendable m_sendable; - private SendableBuilderImpl m_builder; - - ComplexWidget(ShuffleboardContainer parent, String title, Sendable sendable) { - super(parent, title); - m_sendable = sendable; - } - - @Override - public void buildInto(NetworkTable parentTable, NetworkTable metaTable) { - buildMetadata(metaTable); - if (m_builder == null) { - m_builder = new SendableBuilderImpl(); - m_builder.setTable(parentTable.getSubTable(getTitle())); - m_sendable.initSendable(m_builder); - m_builder.startListeners(); - } - m_builder.update(); - } - - /** - * Enables user control of this widget in the Shuffleboard application. This method is - * package-private to prevent users from enabling control themselves. Has no effect if the - * sendable is not marked as an actuator with {@link SendableBuilder#setActuator}. - */ - void enableIfActuator() { - if (m_builder.isActuator()) { - m_builder.startLiveWindowMode(); - } - } - - /** - * Disables user control of this widget in the Shuffleboard application. This method is - * package-private to prevent users from enabling control themselves. Has no effect if the - * sendable is not marked as an actuator with {@link SendableBuilder#setActuator}. - */ - void disableIfActuator() { - if (m_builder.isActuator()) { - m_builder.stopLiveWindowMode(); - } - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ContainerHelper.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ContainerHelper.java deleted file mode 100644 index c8c0731fbc3..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ContainerHelper.java +++ /dev/null @@ -1,190 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; - -import edu.wpi.first.networktables.GenericPublisher; -import edu.wpi.first.networktables.NetworkTableEntry; -import edu.wpi.first.networktables.NetworkTableType; -import edu.wpi.first.util.function.FloatSupplier; -import edu.wpi.first.util.sendable.Sendable; -import edu.wpi.first.util.sendable.SendableRegistry; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BooleanSupplier; -import java.util.function.DoubleSupplier; -import java.util.function.LongSupplier; -import java.util.function.Supplier; - -/** A helper class for Shuffleboard containers to handle common child operations. */ -final class ContainerHelper { - private final ShuffleboardContainer m_container; - private final Set m_usedTitles = new HashSet<>(); - private final List> m_components = new ArrayList<>(); - private final Map m_layouts = new LinkedHashMap<>(); - - ContainerHelper(ShuffleboardContainer container) { - m_container = container; - } - - List> getComponents() { - return m_components; - } - - ShuffleboardLayout getLayout(String title, String type) { - if (!m_layouts.containsKey(title)) { - ShuffleboardLayout layout = new ShuffleboardLayout(m_container, title, type); - m_components.add(layout); - m_layouts.put(title, layout); - } - return m_layouts.get(title); - } - - ShuffleboardLayout getLayout(String title) { - ShuffleboardLayout layout = m_layouts.get(title); - if (layout == null) { - throw new NoSuchElementException("No layout has been defined with the title '" + title + "'"); - } - return layout; - } - - ComplexWidget add(String title, Sendable sendable) { - requireNonNullParam(sendable, "sendable", "add"); - checkTitle(title); - ComplexWidget widget = new ComplexWidget(m_container, title, sendable); - m_components.add(widget); - return widget; - } - - ComplexWidget add(Sendable sendable) { - requireNonNullParam(sendable, "sendable", "add"); - String name = SendableRegistry.getName(sendable); - if (name.isEmpty()) { - throw new IllegalArgumentException("Sendable must have a name"); - } - return add(name, sendable); - } - - SimpleWidget add(String title, Object defaultValue) { - requireNonNullParam(defaultValue, "defaultValue", "add"); - return add(title, NetworkTableType.getStringFromObject(defaultValue), defaultValue); - } - - SimpleWidget add(String title, String typeString, Object defaultValue) { - requireNonNullParam(title, "title", "add"); - requireNonNullParam(defaultValue, "defaultValue", "add"); - checkTitle(title); - checkNtType(defaultValue); - - SimpleWidget widget = new SimpleWidget(m_container, title); - m_components.add(widget); - widget.getEntry(typeString).setDefaultValue(defaultValue); - return widget; - } - - SuppliedValueWidget addString(String title, Supplier valueSupplier) { - precheck(title, valueSupplier, "addString"); - return addSupplied(title, "string", valueSupplier, GenericPublisher::setString); - } - - SuppliedValueWidget addNumber(String title, DoubleSupplier valueSupplier) { - requireNonNullParam(title, "title", "addNumber"); - requireNonNullParam(valueSupplier, "valueSupplier", "addNumber"); - return addDouble(title, valueSupplier); - } - - SuppliedValueWidget addDouble(String title, DoubleSupplier valueSupplier) { - precheck(title, valueSupplier, "addDouble"); - return addSupplied(title, "double", valueSupplier::getAsDouble, GenericPublisher::setDouble); - } - - SuppliedValueWidget addFloat(String title, FloatSupplier valueSupplier) { - precheck(title, valueSupplier, "addFloat"); - return addSupplied(title, "float", valueSupplier::getAsFloat, GenericPublisher::setFloat); - } - - SuppliedValueWidget addInteger(String title, LongSupplier valueSupplier) { - precheck(title, valueSupplier, "addInteger"); - return addSupplied(title, "int", valueSupplier::getAsLong, GenericPublisher::setInteger); - } - - SuppliedValueWidget addBoolean(String title, BooleanSupplier valueSupplier) { - precheck(title, valueSupplier, "addBoolean"); - return addSupplied(title, "boolean", valueSupplier::getAsBoolean, GenericPublisher::setBoolean); - } - - SuppliedValueWidget addStringArray(String title, Supplier valueSupplier) { - precheck(title, valueSupplier, "addStringArray"); - return addSupplied(title, "string[]", valueSupplier, GenericPublisher::setStringArray); - } - - SuppliedValueWidget addDoubleArray(String title, Supplier valueSupplier) { - precheck(title, valueSupplier, "addDoubleArray"); - return addSupplied(title, "double[]", valueSupplier, GenericPublisher::setDoubleArray); - } - - SuppliedValueWidget addFloatArray(String title, Supplier valueSupplier) { - precheck(title, valueSupplier, "addFloatArray"); - return addSupplied(title, "float[]", valueSupplier, GenericPublisher::setFloatArray); - } - - SuppliedValueWidget addIntegerArray(String title, Supplier valueSupplier) { - precheck(title, valueSupplier, "addIntegerArray"); - return addSupplied(title, "int[]", valueSupplier, GenericPublisher::setIntegerArray); - } - - SuppliedValueWidget addBooleanArray(String title, Supplier valueSupplier) { - precheck(title, valueSupplier, "addBooleanArray"); - return addSupplied(title, "boolean[]", valueSupplier, GenericPublisher::setBooleanArray); - } - - SuppliedValueWidget addRaw(String title, Supplier valueSupplier) { - return addRaw(title, "raw", valueSupplier); - } - - SuppliedValueWidget addRaw( - String title, String typeString, Supplier valueSupplier) { - precheck(title, valueSupplier, "addRaw"); - return addSupplied(title, typeString, valueSupplier, GenericPublisher::setRaw); - } - - private void precheck(String title, Object valueSupplier, String methodName) { - requireNonNullParam(title, "title", methodName); - requireNonNullParam(valueSupplier, "valueSupplier", methodName); - checkTitle(title); - } - - private SuppliedValueWidget addSupplied( - String title, - String typeString, - Supplier supplier, - BiConsumer setter) { - SuppliedValueWidget widget = - new SuppliedValueWidget<>(m_container, title, typeString, supplier, setter); - m_components.add(widget); - return widget; - } - - private static void checkNtType(Object data) { - if (!NetworkTableEntry.isValidDataType(data)) { - throw new IllegalArgumentException( - "Cannot add data of type " + data.getClass().getName() + " to Shuffleboard"); - } - } - - private void checkTitle(String title) { - if (m_usedTitles.contains(title)) { - throw new IllegalArgumentException("Title is already in use: " + title); - } - m_usedTitles.add(title); - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/EventImportance.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/EventImportance.java deleted file mode 100644 index 0d85ce69dc7..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/EventImportance.java +++ /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. - -package edu.wpi.first.wpilibj.shuffleboard; - -/** - * The importance of an event marker in Shuffleboard. The exact meaning of each importance level is - * up for interpretation on a team-to-team basis, but users should follow the general guidelines of - * the various importance levels. The examples given are for reference and may be ignored or - * considered to be more or less important from team to team. - */ -public enum EventImportance { - // Maintainer note: this enum is mirrored in WPILibC and in Shuffleboard - // Modifying the enum or enum strings requires a corresponding change to the C++ enum - // and the enum in Shuffleboard - - /** A trivial event such as a change in command state. */ - kTrivial("TRIVIAL"), - - /** A low importance event such as acquisition of a game piece. */ - kLow("LOW"), - - /** - * A "normal" importance event, such as a transition from autonomous mode to teleoperated control. - */ - kNormal("NORMAL"), - - /** A high-importance event such as scoring a game piece. */ - kHigh("HIGH"), - - /** A critically important event such as a brownout, component failure, or software deadlock. */ - kCritical("CRITICAL"); - - private final String m_simpleName; - - EventImportance(String simpleName) { - m_simpleName = simpleName; - } - - /** - * Returns name of the given enum. - * - * @return Name of the given enum. - */ - public String getSimpleName() { - return m_simpleName; - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/LayoutType.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/LayoutType.java deleted file mode 100644 index 82ffcbef204..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/LayoutType.java +++ /dev/null @@ -1,20 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -/** - * Represents the type of a layout in Shuffleboard. Using this is preferred over specifying raw - * strings, to avoid typos and having to know or look up the exact string name for a desired layout. - * - * @see BuiltInWidgets the built-in widget types - */ -public interface LayoutType { - /** - * Gets the string type of the layout as defined by that layout in Shuffleboard. - * - * @return The string type of the layout. - */ - String getLayoutName(); -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/RecordingController.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/RecordingController.java deleted file mode 100644 index f8329ddbc1a..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/RecordingController.java +++ /dev/null @@ -1,65 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import edu.wpi.first.networktables.BooleanPublisher; -import edu.wpi.first.networktables.NetworkTable; -import edu.wpi.first.networktables.NetworkTableInstance; -import edu.wpi.first.networktables.StringPublisher; -import edu.wpi.first.wpilibj.DriverStation; - -/** Controls Shuffleboard recordings via NetworkTables. */ -final class RecordingController { - private static final String kRecordingTableName = "/Shuffleboard/.recording/"; - private static final String kRecordingControlKey = kRecordingTableName + "RecordData"; - private static final String kRecordingFileNameFormatKey = kRecordingTableName + "FileNameFormat"; - private static final String kEventMarkerTableName = kRecordingTableName + "events"; - - private final BooleanPublisher m_recordingControlEntry; - private final StringPublisher m_recordingFileNameFormatEntry; - private final NetworkTable m_eventsTable; - - RecordingController(NetworkTableInstance ntInstance) { - m_recordingControlEntry = ntInstance.getBooleanTopic(kRecordingControlKey).publish(); - m_recordingFileNameFormatEntry = - ntInstance.getStringTopic(kRecordingFileNameFormatKey).publish(); - m_eventsTable = ntInstance.getTable(kEventMarkerTableName); - } - - public void startRecording() { - m_recordingControlEntry.set(true); - } - - public void stopRecording() { - m_recordingControlEntry.set(false); - } - - public void setRecordingFileNameFormat(String format) { - m_recordingFileNameFormatEntry.set(format); - } - - public void clearRecordingFileNameFormat() { - m_recordingFileNameFormatEntry.set(""); - } - - public void addEventMarker(String name, String description, EventImportance importance) { - if (name == null || name.isEmpty()) { - DriverStation.reportError("Shuffleboard event name was not specified", true); - return; - } - - if (importance == null) { - DriverStation.reportError("Shuffleboard event importance was null", true); - return; - } - - String eventDescription = description == null ? "" : description; - - m_eventsTable - .getSubTable(name) - .getEntry("Info") - .setStringArray(new String[] {eventDescription, importance.getSimpleName()}); - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SendableCameraWrapper.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SendableCameraWrapper.java deleted file mode 100644 index bd428cdd00b..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SendableCameraWrapper.java +++ /dev/null @@ -1,138 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; - -import edu.wpi.first.cscore.VideoSource; -import edu.wpi.first.networktables.NetworkTable; -import edu.wpi.first.networktables.NetworkTableInstance; -import edu.wpi.first.networktables.StringArrayPublisher; -import edu.wpi.first.networktables.StringArrayTopic; -import edu.wpi.first.util.sendable.Sendable; -import edu.wpi.first.util.sendable.SendableBuilder; -import edu.wpi.first.util.sendable.SendableRegistry; -import java.util.Map; -import java.util.Objects; -import java.util.WeakHashMap; - -/** A wrapper to make video sources sendable and usable from Shuffleboard. */ -public final class SendableCameraWrapper implements Sendable, AutoCloseable { - private static final String kProtocol = "camera_server://"; - - private static Map m_wrappers = new WeakHashMap<>(); - - private static NetworkTable m_table; - - static { - setNetworkTableInstance(NetworkTableInstance.getDefault()); - } - - private final String m_uri; - private StringArrayPublisher m_streams; - - /** - * Creates a new sendable wrapper. Private constructor to avoid direct instantiation with multiple - * wrappers floating around for the same camera. - * - * @param source the source to wrap - */ - private SendableCameraWrapper(VideoSource source) { - this(source.getName()); - } - - private SendableCameraWrapper(String cameraName) { - SendableRegistry.add(this, cameraName); - m_uri = kProtocol + cameraName; - } - - private SendableCameraWrapper(String cameraName, String[] cameraUrls) { - this(cameraName); - - StringArrayTopic streams = new StringArrayTopic(m_table.getTopic(cameraName + "/streams")); - if (streams.exists()) { - throw new IllegalStateException( - "A camera is already being streamed with the name '" + cameraName + "'"); - } - - m_streams = streams.publish(); - m_streams.set(cameraUrls); - } - - /** Clears all cached wrapper objects. This should only be used in tests. */ - static void clearWrappers() { - m_wrappers.clear(); - } - - @Override - public void close() { - SendableRegistry.remove(this); - if (m_streams != null) { - m_streams.close(); - } - } - - /** - * Sets NetworkTable instance used for camera publisher entries. - * - * @param inst NetworkTable instance - */ - public static synchronized void setNetworkTableInstance(NetworkTableInstance inst) { - m_table = inst.getTable("CameraPublisher"); - } - - /** - * Gets a sendable wrapper object for the given video source, creating the wrapper if one does not - * already exist for the source. - * - * @param source the video source to wrap - * @return a sendable wrapper object for the video source, usable in Shuffleboard via {@link - * ShuffleboardTab#add(Sendable)} and {@link ShuffleboardLayout#add(Sendable)} - */ - public static SendableCameraWrapper wrap(VideoSource source) { - return m_wrappers.computeIfAbsent(source.getName(), name -> new SendableCameraWrapper(source)); - } - - /** - * Creates a wrapper for an arbitrary camera stream. The stream URLs must be specified - * using a host resolvable by a program running on a different host (such as a dashboard); prefer - * using static IP addresses (if known) or DHCP identifiers such as {@code "raspberrypi.local"}. - * - *

If a wrapper already exists for the given camera, that wrapper is returned and the specified - * URLs are ignored. - * - * @param cameraName the name of the camera. Cannot be null or empty - * @param cameraUrls the URLs with which the camera stream may be accessed. At least one URL must - * be specified - * @return a sendable wrapper object for the video source, usable in Shuffleboard via {@link - * ShuffleboardTab#add(Sendable)} and {@link ShuffleboardLayout#add(Sendable)} - */ - public static SendableCameraWrapper wrap(String cameraName, String... cameraUrls) { - if (m_wrappers.containsKey(cameraName)) { - return m_wrappers.get(cameraName); - } - - requireNonNullParam(cameraName, "cameraName", "wrap"); - requireNonNullParam(cameraUrls, "cameraUrls", "wrap"); - if (cameraName.isEmpty()) { - throw new IllegalArgumentException("Camera name not specified"); - } - if (cameraUrls.length == 0) { - throw new IllegalArgumentException("No camera URLs specified"); - } - for (int i = 0; i < cameraUrls.length; i++) { - Objects.requireNonNull(cameraUrls[i], "Camera URL at index " + i + " was null"); - } - - SendableCameraWrapper wrapper = new SendableCameraWrapper(cameraName, cameraUrls); - m_wrappers.put(cameraName, wrapper); - return wrapper; - } - - @Override - public void initSendable(SendableBuilder builder) { - builder.addStringProperty(".ShuffleboardURI", () -> m_uri, null); - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/Shuffleboard.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/Shuffleboard.java deleted file mode 100644 index c08ab6ffeb6..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/Shuffleboard.java +++ /dev/null @@ -1,195 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import edu.wpi.first.networktables.NetworkTableInstance; - -/** - * The Shuffleboard class provides a mechanism with which data can be added and laid out in the - * Shuffleboard dashboard application from a robot program. Tabs and layouts can be specified, as - * well as choosing which widgets to display with and setting properties of these widgets; for - * example, programmers can specify a specific {@code boolean} value to be displayed with a toggle - * button instead of the default colored box, or set custom colors for that box. - * - *

For example, displaying a boolean entry with a toggle button: - * - *

{@code
- * GenericEntry myBoolean = Shuffleboard.getTab("Example Tab")
- *   .add("My Boolean", false)
- *   .withWidget("Toggle Button")
- *   .getEntry();
- * }
- * - *

Changing the colors of the boolean box: - * - *

{@code
- * GenericEntry myBoolean = Shuffleboard.getTab("Example Tab")
- *   .add("My Boolean", false)
- *   .withWidget("Boolean Box")
- *   .withProperties(Map.of("colorWhenTrue", "green", "colorWhenFalse", "maroon"))
- *   .getEntry();
- * }
- * - *

Specifying a parent layout. Note that the layout type must always be specified, even if - * the layout has already been generated by a previously defined entry. - * - *

{@code
- * GenericEntry myBoolean = Shuffleboard.getTab("Example Tab")
- *   .getLayout("List", "Example List")
- *   .add("My Boolean", false)
- *   .withWidget("Toggle Button")
- *   .getEntry();
- * }
- * - *

Teams are encouraged to set up shuffleboard layouts at the start of the robot program. - */ -public final class Shuffleboard { - /** The name of the base NetworkTable into which all Shuffleboard data will be added. */ - public static final String kBaseTableName = "/Shuffleboard"; - - private static final ShuffleboardRoot root = - new ShuffleboardInstance(NetworkTableInstance.getDefault()); - private static final RecordingController recordingController = - new RecordingController(NetworkTableInstance.getDefault()); - - private Shuffleboard() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } - - /** - * Updates all the values in Shuffleboard. Iterative and timed robots are pre-configured to call - * this method in the main robot loop; teams using custom robot base classes, or subclass - * SampleRobot, should make sure to call this repeatedly to keep data on the dashboard up to date. - */ - public static void update() { - root.update(); - } - - /** - * Gets the Shuffleboard tab with the given title, creating it if it does not already exist. - * - * @param title the title of the tab - * @return the tab with the given title - */ - public static ShuffleboardTab getTab(String title) { - return root.getTab(title); - } - - /** - * Selects the tab in the dashboard with the given index in the range [0..n-1], where n is - * the number of tabs in the dashboard at the time this method is called. - * - * @param index the index of the tab to select - */ - public static void selectTab(int index) { - root.selectTab(index); - } - - /** - * Selects the tab in the dashboard with the given title. - * - * @param title the title of the tab to select - */ - public static void selectTab(String title) { - root.selectTab(title); - } - - /** - * Enables user control of widgets containing actuators: motor controllers, relays, etc. This - * should only be used when the robot is in test mode. IterativeRobotBase and SampleRobot are both - * configured to call this method when entering test mode; most users should not need to use this - * method directly. - */ - public static void enableActuatorWidgets() { - root.enableActuatorWidgets(); - } - - /** - * Disables user control of widgets containing actuators. For safety reasons, actuators should - * only be controlled while in test mode. IterativeRobotBase and SampleRobot are both configured - * to call this method when exiting in test mode; most users should not need to use this method - * directly. - */ - public static void disableActuatorWidgets() { - update(); // Need to update to make sure the sendable builders are initialized - root.disableActuatorWidgets(); - } - - /** - * Starts data recording on the dashboard. Has no effect if recording is already in progress. - * - * @see #stopRecording() - */ - public static void startRecording() { - recordingController.startRecording(); - } - - /** - * Stops data recording on the dashboard. Has no effect if no recording is in progress. - * - * @see #startRecording() - */ - public static void stopRecording() { - recordingController.stopRecording(); - } - - /** - * Sets the file name format for new recording files to use. If recording is in progress when this - * method is called, it will continue to use the same file. New recordings will use the format. - * - *

To avoid recording files overwriting each other, make sure to use unique recording file - * names. File name formats accept templates for inserting the date and time when the recording - * started with the {@code ${date}} and {@code ${time}} templates, respectively. For example, the - * default format is {@code "recording-${time}"} and recording files created with it will have - * names like {@code "recording-2018.01.15.sbr"}. Users are strongly recommended - * to use the {@code ${time}} template to ensure unique file names. - * - * @param format the format for the - * @see #clearRecordingFileNameFormat() - */ - public static void setRecordingFileNameFormat(String format) { - recordingController.setRecordingFileNameFormat(format); - } - - /** - * Clears the custom name format for recording files. New recordings will use the default format. - * - * @see #setRecordingFileNameFormat(String) - */ - public static void clearRecordingFileNameFormat() { - recordingController.clearRecordingFileNameFormat(); - } - - /** - * Notifies Shuffleboard of an event. Events can range from as trivial as a change in a command - * state to as critical as a total power loss or component failure. If Shuffleboard is recording, - * the event will also be recorded. - * - *

If {@code name} is {@code null} or empty, or {@code importance} is {@code null}, then no - * event will be sent and an error will be printed to the driver station. - * - * @param name the name of the event - * @param description a description of the event - * @param importance the importance of the event - */ - public static void addEventMarker(String name, String description, EventImportance importance) { - recordingController.addEventMarker(name, description, importance); - } - - /** - * Notifies Shuffleboard of an event. Events can range from as trivial as a change in a command - * state to as critical as a total power loss or component failure. If Shuffleboard is recording, - * the event will also be recorded. - * - *

If {@code name} is {@code null} or empty, or {@code importance} is {@code null}, then no - * event will be sent and an error will be printed to the driver station. - * - * @param name the name of the event - * @param importance the importance of the event - */ - public static void addEventMarker(String name, EventImportance importance) { - addEventMarker(name, "", importance); - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardComponent.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardComponent.java deleted file mode 100644 index 3e1f75acd89..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardComponent.java +++ /dev/null @@ -1,177 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; - -import edu.wpi.first.networktables.NetworkTable; -import java.util.Map; - -/** - * A generic component in Shuffleboard. - * - * @param the self type - */ -public abstract class ShuffleboardComponent> - implements ShuffleboardValue { - private final ShuffleboardContainer m_parent; - private final String m_title; - private String m_type; - private Map m_properties; - private boolean m_metadataDirty = true; - private int m_column = -1; - private int m_row = -1; - private int m_width = -1; - private int m_height = -1; - - /** - * Constructs a ShuffleboardComponent. - * - * @param parent The parent container. - * @param title The component title. - * @param type The component type. - */ - protected ShuffleboardComponent(ShuffleboardContainer parent, String title, String type) { - m_parent = requireNonNullParam(parent, "parent", "ShuffleboardComponent"); - m_title = requireNonNullParam(title, "title", "ShuffleboardComponent"); - m_type = type; - } - - /** - * Constructs a ShuffleboardComponent. - * - * @param parent The parent container. - * @param title The component title. - */ - protected ShuffleboardComponent(ShuffleboardContainer parent, String title) { - this(parent, title, null); - } - - /** - * Returns the parent container. - * - * @return The parent container. - */ - public final ShuffleboardContainer getParent() { - return m_parent; - } - - /** - * Sets the component type. - * - * @param type The component type. - */ - protected final void setType(String type) { - m_type = type; - m_metadataDirty = true; - } - - /** - * Returns the component type. - * - * @return The component type. - */ - public final String getType() { - return m_type; - } - - @Override - public final String getTitle() { - return m_title; - } - - /** Gets the custom properties for this component. May be null. */ - final Map getProperties() { - return m_properties; - } - - /** - * Sets custom properties for this component. Property names are case- and whitespace-insensitive - * (capitalization and spaces do not matter). - * - * @param properties the properties for this component - * @return this component - */ - @SuppressWarnings("unchecked") - public final C withProperties(Map properties) { - m_properties = properties; - m_metadataDirty = true; - return (C) this; - } - - /** - * Sets the position of this component in the tab. This has no effect if this component is inside - * a layout. - * - *

If the position of a single component is set, it is recommended to set the positions of - * all components inside a tab to prevent Shuffleboard from automatically placing another - * component there before the one with the specific position is sent. - * - * @param columnIndex the column in the tab to place this component - * @param rowIndex the row in the tab to place this component - * @return this component - */ - @SuppressWarnings("unchecked") - public final C withPosition(int columnIndex, int rowIndex) { - m_column = columnIndex; - m_row = rowIndex; - m_metadataDirty = true; - return (C) this; - } - - /** - * Sets the size of this component in the tab. This has no effect if this component is inside a - * layout. - * - * @param width how many columns wide the component should be - * @param height how many rows high the component should be - * @return this component - */ - @SuppressWarnings("unchecked") - public final C withSize(int width, int height) { - m_width = width; - m_height = height; - m_metadataDirty = true; - return (C) this; - } - - /** - * Builds NT metadata. - * - * @param metaTable The NT metadata table. - */ - protected final void buildMetadata(NetworkTable metaTable) { - if (!m_metadataDirty) { - return; - } - // Component type - if (getType() == null) { - metaTable.getEntry("PreferredComponent").unpublish(); - } else { - metaTable.getEntry("PreferredComponent").setString(getType()); - } - - // Tile size - if (m_width <= 0 || m_height <= 0) { - metaTable.getEntry("Size").unpublish(); - } else { - metaTable.getEntry("Size").setDoubleArray(new double[] {m_width, m_height}); - } - - // Tile position - if (m_column < 0 || m_row < 0) { - metaTable.getEntry("Position").unpublish(); - } else { - metaTable.getEntry("Position").setDoubleArray(new double[] {m_column, m_row}); - } - - // Custom properties - if (getProperties() != null) { - NetworkTable propTable = metaTable.getSubTable("Properties"); - getProperties().forEach((name, value) -> propTable.getEntry(name).setValue(value)); - } - m_metadataDirty = false; - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardContainer.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardContainer.java deleted file mode 100644 index 5e08d4dfd69..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardContainer.java +++ /dev/null @@ -1,363 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import edu.wpi.first.cscore.VideoSource; -import edu.wpi.first.networktables.NetworkTableType; -import edu.wpi.first.util.function.FloatSupplier; -import edu.wpi.first.util.sendable.Sendable; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.function.BooleanSupplier; -import java.util.function.DoubleSupplier; -import java.util.function.LongSupplier; -import java.util.function.Supplier; - -/** Common interface for objects that can contain shuffleboard components. */ -public sealed interface ShuffleboardContainer extends ShuffleboardValue - permits ShuffleboardLayout, ShuffleboardTab { - /** - * Gets the components that are direct children of this container. - * - * @return The components that are direct children of this container. - */ - List> getComponents(); - - /** - * Gets the layout with the given type and title, creating it if it does not already exist at the - * time this method is called. Note: this method should only be used to use a layout type that is - * not already built into Shuffleboard. To use a layout built into Shuffleboard, use {@link - * #getLayout(String, LayoutType)} and the layouts in {@link BuiltInLayouts}. - * - * @param title the title of the layout - * @param type the type of the layout, eg "List Layout" or "Grid Layout" - * @return the layout - * @see #getLayout(String, LayoutType) - */ - ShuffleboardLayout getLayout(String title, String type); - - /** - * Gets the layout with the given type and title, creating it if it does not already exist at the - * time this method is called. - * - * @param title the title of the layout - * @param layoutType the type of the layout, eg "List" or "Grid" - * @return the layout - */ - default ShuffleboardLayout getLayout(String title, LayoutType layoutType) { - return getLayout(title, layoutType.getLayoutName()); - } - - /** - * Gets the already-defined layout in this container with the given title. - * - *

{@code
-   * Shuffleboard.getTab("Example Tab")
-   *   .getLayout("My Layout", BuiltInLayouts.kList);
-   *
-   * // Later...
-   * Shuffleboard.getTab("Example Tab")
-   *   .getLayout("My Layout");
-   * }
- * - * @param title the title of the layout to get - * @return the layout with the given title - * @throws NoSuchElementException if no layout has yet been defined with the given title - */ - ShuffleboardLayout getLayout(String title); - - /** - * Adds a widget to this container to display the given sendable. - * - * @param title the title of the widget - * @param sendable the sendable to display - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - ComplexWidget add(String title, Sendable sendable); - - /** - * Adds a widget to this container to display the given video stream. - * - * @param title the title of the widget - * @param video the video stream to display - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - default ComplexWidget add(String title, VideoSource video) { - return add(title, SendableCameraWrapper.wrap(video)); - } - - /** - * Adds a widget to this container to display the given sendable. - * - * @param sendable the sendable to display - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title, or if the sendable's name has not been specified - */ - ComplexWidget add(Sendable sendable); - - /** - * Adds a widget to this container to display the given video stream. - * - * @param video the video to display - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this container with the same - * title as the video source - */ - default ComplexWidget add(VideoSource video) { - return add(SendableCameraWrapper.wrap(video)); - } - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - * @see #addPersistent(String, Object) add(String title, Object defaultValue) - */ - SimpleWidget add(String title, Object defaultValue); - - /** - * Adds a widget to this container to display the given data. - * - * @param title the title of the widget - * @param typeString the NT type string - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - * @see #addPersistent(String, Object) add(String title, Object defaultValue) - */ - SimpleWidget add(String title, String typeString, Object defaultValue); - - /** - * Adds a widget to this container to display a video stream. - * - * @param title the title of the widget - * @param cameraName the name of the streamed camera - * @param cameraUrls the URLs with which the dashboard can access the camera stream - * @return a widget to display the camera stream - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - default ComplexWidget addCamera(String title, String cameraName, String... cameraUrls) { - return add(title, SendableCameraWrapper.wrap(cameraName, cameraUrls)); - } - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addString(String title, Supplier valueSupplier); - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addNumber(String title, DoubleSupplier valueSupplier); - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addDouble(String title, DoubleSupplier valueSupplier); - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addFloat(String title, FloatSupplier valueSupplier); - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addInteger(String title, LongSupplier valueSupplier); - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addBoolean(String title, BooleanSupplier valueSupplier); - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addStringArray(String title, Supplier valueSupplier); - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addDoubleArray(String title, Supplier valueSupplier); - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addFloatArray(String title, Supplier valueSupplier); - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addIntegerArray(String title, Supplier valueSupplier); - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addBooleanArray(String title, Supplier valueSupplier); - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - default SuppliedValueWidget addRaw(String title, Supplier valueSupplier) { - return addRaw(title, "raw", valueSupplier); - } - - /** - * Adds a widget to this container. The widget will display the data provided by the value - * supplier. Changes made on the dashboard will not propagate to the widget object, and will be - * overridden by values from the value supplier. - * - * @param title the title of the widget - * @param typeString the NT type string for the value - * @param valueSupplier the supplier for values - * @return a widget to display data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - */ - SuppliedValueWidget addRaw( - String title, String typeString, Supplier valueSupplier); - - /** - * Adds a widget to this container to display a simple piece of data. Unlike {@link #add(String, - * Object)}, the value in the widget will be saved on the robot and will be used when the robot - * program next starts rather than {@code defaultValue}. - * - * @param title the title of the widget - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - * @see #add(String, Object) add(String title, Object defaultValue) - */ - default SimpleWidget addPersistent(String title, Object defaultValue) { - return addPersistent(title, NetworkTableType.getStringFromObject(defaultValue), defaultValue); - } - - /** - * Adds a widget to this container to display a simple piece of data. Unlike {@link #add(String, - * Object)}, the value in the widget will be saved on the robot and will be used when the robot - * program next starts rather than {@code defaultValue}. - * - * @param title the title of the widget - * @param typeString the NT type string - * @param defaultValue the default value of the widget - * @return a widget to display the sendable data - * @throws IllegalArgumentException if a widget already exists in this container with the given - * title - * @see #add(String, Object) add(String title, Object defaultValue) - */ - default SimpleWidget addPersistent(String title, String typeString, Object defaultValue) { - SimpleWidget widget = add(title, defaultValue); - widget.getEntry(typeString).getTopic().setPersistent(true); - return widget; - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardInstance.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardInstance.java deleted file mode 100644 index fb8a3b5b76f..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardInstance.java +++ /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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; - -import edu.wpi.first.hal.FRCNetComm.tResourceType; -import edu.wpi.first.hal.HAL; -import edu.wpi.first.networktables.NetworkTable; -import edu.wpi.first.networktables.NetworkTableInstance; -import edu.wpi.first.networktables.PubSubOption; -import edu.wpi.first.networktables.StringPublisher; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.Consumer; - -final class ShuffleboardInstance implements ShuffleboardRoot { - private final Map m_tabs = new LinkedHashMap<>(); - private boolean m_reported = false; // NOPMD redundant field initializer - private boolean m_tabsChanged = false; // NOPMD redundant field initializer - private final NetworkTable m_rootTable; - private final NetworkTable m_rootMetaTable; - private final StringPublisher m_selectedTabPub; - - /** - * Creates a new Shuffleboard instance. - * - * @param ntInstance the NetworkTables instance to use - */ - ShuffleboardInstance(NetworkTableInstance ntInstance) { - requireNonNullParam(ntInstance, "ntInstance", "ShuffleboardInstance"); - m_rootTable = ntInstance.getTable(Shuffleboard.kBaseTableName); - m_rootMetaTable = m_rootTable.getSubTable(".metadata"); - m_selectedTabPub = - m_rootMetaTable.getStringTopic("Selected").publish(PubSubOption.keepDuplicates(true)); - } - - @Override - public ShuffleboardTab getTab(String title) { - requireNonNullParam(title, "title", "getTab"); - if (!m_reported) { - HAL.report(tResourceType.kResourceType_Shuffleboard, 0); - m_reported = true; - } - if (!m_tabs.containsKey(title)) { - m_tabs.put(title, new ShuffleboardTab(this, title)); - m_tabsChanged = true; - } - return m_tabs.get(title); - } - - @Override - public void update() { - if (m_tabsChanged) { - String[] tabTitles = - m_tabs.values().stream().map(ShuffleboardTab::getTitle).toArray(String[]::new); - m_rootMetaTable.getEntry("Tabs").setStringArray(tabTitles); - m_tabsChanged = false; - } - for (ShuffleboardTab tab : m_tabs.values()) { - String title = tab.getTitle(); - tab.buildInto(m_rootTable, m_rootMetaTable.getSubTable(title)); - } - } - - @Override - public void enableActuatorWidgets() { - applyToAllComplexWidgets(ComplexWidget::enableIfActuator); - } - - @Override - public void disableActuatorWidgets() { - applyToAllComplexWidgets(ComplexWidget::disableIfActuator); - } - - @Override - public void selectTab(int index) { - selectTab(Integer.toString(index)); - } - - @Override - public void selectTab(String title) { - m_selectedTabPub.set(title); - } - - /** - * Applies the function {@code func} to all complex widgets in this root, regardless of how they - * are nested. - * - * @param func the function to apply to all complex widgets - */ - private void applyToAllComplexWidgets(Consumer func) { - for (ShuffleboardTab tab : m_tabs.values()) { - apply(tab, func); - } - } - - /** - * Applies the function {@code func} to all complex widgets in {@code container}. Helper method - * for {@link #applyToAllComplexWidgets}. - */ - private void apply(ShuffleboardContainer container, Consumer func) { - for (ShuffleboardComponent component : container.getComponents()) { - if (component instanceof ComplexWidget widget) { - func.accept(widget); - } - if (component instanceof ShuffleboardContainer nestedContainer) { - apply(nestedContainer, func); - } - } - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardLayout.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardLayout.java deleted file mode 100644 index 564f5e42619..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardLayout.java +++ /dev/null @@ -1,141 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; - -import edu.wpi.first.networktables.NetworkTable; -import edu.wpi.first.util.function.FloatSupplier; -import edu.wpi.first.util.sendable.Sendable; -import java.util.List; -import java.util.function.BooleanSupplier; -import java.util.function.DoubleSupplier; -import java.util.function.LongSupplier; -import java.util.function.Supplier; - -/** A layout in a Shuffleboard tab. Layouts can contain widgets and other layouts. */ -public final class ShuffleboardLayout extends ShuffleboardComponent - implements ShuffleboardContainer { - private static final String kSmartDashboardType = "ShuffleboardLayout"; - - private final ContainerHelper m_helper = new ContainerHelper(this); - - ShuffleboardLayout(ShuffleboardContainer parent, String title, String type) { - super(parent, title, requireNonNullParam(type, "type", "ShuffleboardLayout")); - } - - @Override - public List> getComponents() { - return m_helper.getComponents(); - } - - @Override - public ShuffleboardLayout getLayout(String title, String type) { - return m_helper.getLayout(title, type); - } - - @Override - public ShuffleboardLayout getLayout(String title) { - return m_helper.getLayout(title); - } - - @Override - public ComplexWidget add(String title, Sendable sendable) { - return m_helper.add(title, sendable); - } - - @Override - public ComplexWidget add(Sendable sendable) { - return m_helper.add(sendable); - } - - @Override - public SimpleWidget add(String title, Object defaultValue) { - return m_helper.add(title, defaultValue); - } - - @Override - public SimpleWidget add(String title, String typeString, Object defaultValue) { - return m_helper.add(title, typeString, defaultValue); - } - - @Override - public SuppliedValueWidget addString(String title, Supplier valueSupplier) { - return m_helper.addString(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addNumber(String title, DoubleSupplier valueSupplier) { - return m_helper.addNumber(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addDouble(String title, DoubleSupplier valueSupplier) { - return m_helper.addDouble(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addFloat(String title, FloatSupplier valueSupplier) { - return m_helper.addFloat(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addInteger(String title, LongSupplier valueSupplier) { - return m_helper.addInteger(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addBoolean(String title, BooleanSupplier valueSupplier) { - return m_helper.addBoolean(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addStringArray( - String title, Supplier valueSupplier) { - return m_helper.addStringArray(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addDoubleArray( - String title, Supplier valueSupplier) { - return m_helper.addDoubleArray(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addFloatArray(String title, Supplier valueSupplier) { - return m_helper.addFloatArray(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addIntegerArray(String title, Supplier valueSupplier) { - return m_helper.addIntegerArray(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addBooleanArray( - String title, Supplier valueSupplier) { - return m_helper.addBooleanArray(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addRaw( - String title, String typeString, Supplier valueSupplier) { - return m_helper.addRaw(title, typeString, valueSupplier); - } - - @Override - public void buildInto(NetworkTable parentTable, NetworkTable metaTable) { - buildMetadata(metaTable); - NetworkTable table = parentTable.getSubTable(getTitle()); - table.getEntry(".type").setString(kSmartDashboardType); - table - .getEntry(".type") - .getTopic() - .setProperty("SmartDashboard", "\"" + kSmartDashboardType + "\""); - for (ShuffleboardComponent component : getComponents()) { - component.buildInto(table, metaTable.getSubTable(component.getTitle())); - } - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardRoot.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardRoot.java deleted file mode 100644 index fa6cd08deb8..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardRoot.java +++ /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. - -package edu.wpi.first.wpilibj.shuffleboard; - -/** - * The root of the data placed in Shuffleboard. It contains the tabs, but no data is placed directly - * in the root. - * - *

This class is package-private to minimize API surface area. - */ -interface ShuffleboardRoot { - /** - * Gets the tab with the given title, creating it if it does not already exist. - * - * @param title the title of the tab - * @return the tab with the given title - */ - ShuffleboardTab getTab(String title); - - /** Updates all tabs. */ - void update(); - - /** Enables all widgets in Shuffleboard that offer user control over actuators. */ - void enableActuatorWidgets(); - - /** Disables all widgets in Shuffleboard that offer user control over actuators. */ - void disableActuatorWidgets(); - - /** - * Selects the tab in the dashboard with the given index in the range [0..n-1], where n is - * the number of tabs in the dashboard at the time this method is called. - * - * @param index the index of the tab to select - */ - void selectTab(int index); - - /** - * Selects the tab in the dashboard with the given title. - * - * @param title the title of the tab to select - */ - void selectTab(String title); -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardTab.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardTab.java deleted file mode 100644 index b71255de763..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardTab.java +++ /dev/null @@ -1,154 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import edu.wpi.first.networktables.NetworkTable; -import edu.wpi.first.util.function.FloatSupplier; -import edu.wpi.first.util.sendable.Sendable; -import java.util.List; -import java.util.function.BooleanSupplier; -import java.util.function.DoubleSupplier; -import java.util.function.LongSupplier; -import java.util.function.Supplier; - -/** - * Represents a tab in the Shuffleboard dashboard. Widgets can be added to the tab with {@link - * #add(Sendable)}, {@link #add(String, Object)}, and {@link #add(String, Sendable)}. Widgets can - * also be added to layouts with {@link #getLayout(String, String)}; layouts can be nested - * arbitrarily deep (note that too many levels may make deeper components unusable). - */ -public final class ShuffleboardTab implements ShuffleboardContainer { - private static final String kSmartDashboardType = "ShuffleboardTab"; - - private final ContainerHelper m_helper = new ContainerHelper(this); - private final ShuffleboardRoot m_root; - private final String m_title; - - ShuffleboardTab(ShuffleboardRoot root, String title) { - m_root = root; - m_title = title; - } - - @Override - public String getTitle() { - return m_title; - } - - ShuffleboardRoot getRoot() { - return m_root; - } - - @Override - public List> getComponents() { - return m_helper.getComponents(); - } - - @Override - public ShuffleboardLayout getLayout(String title, String type) { - return m_helper.getLayout(title, type); - } - - @Override - public ShuffleboardLayout getLayout(String title) { - return m_helper.getLayout(title); - } - - @Override - public ComplexWidget add(String title, Sendable sendable) { - return m_helper.add(title, sendable); - } - - @Override - public ComplexWidget add(Sendable sendable) { - return m_helper.add(sendable); - } - - @Override - public SimpleWidget add(String title, Object defaultValue) { - return m_helper.add(title, defaultValue); - } - - @Override - public SimpleWidget add(String title, String typeString, Object defaultValue) { - return m_helper.add(title, typeString, defaultValue); - } - - @Override - public SuppliedValueWidget addString(String title, Supplier valueSupplier) { - return m_helper.addString(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addNumber(String title, DoubleSupplier valueSupplier) { - return m_helper.addNumber(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addDouble(String title, DoubleSupplier valueSupplier) { - return m_helper.addDouble(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addFloat(String title, FloatSupplier valueSupplier) { - return m_helper.addFloat(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addInteger(String title, LongSupplier valueSupplier) { - return m_helper.addInteger(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addBoolean(String title, BooleanSupplier valueSupplier) { - return m_helper.addBoolean(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addStringArray( - String title, Supplier valueSupplier) { - return m_helper.addStringArray(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addDoubleArray( - String title, Supplier valueSupplier) { - return m_helper.addDoubleArray(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addFloatArray(String title, Supplier valueSupplier) { - return m_helper.addFloatArray(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addIntegerArray(String title, Supplier valueSupplier) { - return m_helper.addIntegerArray(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addBooleanArray( - String title, Supplier valueSupplier) { - return m_helper.addBooleanArray(title, valueSupplier); - } - - @Override - public SuppliedValueWidget addRaw( - String title, String typeString, Supplier valueSupplier) { - return m_helper.addRaw(title, typeString, valueSupplier); - } - - @Override - public void buildInto(NetworkTable parentTable, NetworkTable metaTable) { - NetworkTable tabTable = parentTable.getSubTable(m_title); - tabTable.getEntry(".type").setString(kSmartDashboardType); - tabTable - .getEntry(".type") - .getTopic() - .setProperty("SmartDashboard", "\"" + kSmartDashboardType + "\""); - for (ShuffleboardComponent component : m_helper.getComponents()) { - component.buildInto(tabTable, metaTable.getSubTable(component.getTitle())); - } - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardValue.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardValue.java deleted file mode 100644 index 88f43896728..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardValue.java +++ /dev/null @@ -1,27 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import edu.wpi.first.networktables.NetworkTable; - -interface ShuffleboardValue { - /** - * Gets the title of this Shuffleboard value. - * - * @return The title of this Shuffleboard value. - */ - String getTitle(); - - /** - * Builds the entries for this value. - * - * @param parentTable the table containing all the data for the parent. Values that require a - * complex entry or table structure should call {@code parentTable.getSubTable(getTitle())} to - * get the table to put data into. Values that only use a single entry should call {@code - * parentTable.getEntry(getTitle())} to get that entry. - * @param metaTable the table containing all the metadata for this value and its sub-values - */ - void buildInto(NetworkTable parentTable, NetworkTable metaTable); -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardWidget.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardWidget.java deleted file mode 100644 index 39ce03613e9..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardWidget.java +++ /dev/null @@ -1,46 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -/** - * Abstract superclass for widgets. - * - *

This class is package-private to minimize API surface area. - * - * @param the self type - */ -abstract class ShuffleboardWidget> - extends ShuffleboardComponent { - ShuffleboardWidget(ShuffleboardContainer parent, String title) { - super(parent, title); - } - - /** - * Sets the type of widget used to display the data. If not set, the default widget type will be - * used. - * - * @param widgetType the type of the widget used to display the data - * @return this widget object - * @see BuiltInWidgets - */ - public final W withWidget(WidgetType widgetType) { - return withWidget(widgetType.getWidgetName()); - } - - /** - * Sets the type of widget used to display the data. If not set, the default widget type will be - * used. This method should only be used to use a widget that does not come built into - * Shuffleboard (i.e. one that comes with a custom or third-party plugin). To use a widget that is - * built into Shuffleboard, use {@link #withWidget(WidgetType)} and {@link BuiltInWidgets}. - * - * @param widgetType the type of the widget used to display the data - * @return this widget object - */ - @SuppressWarnings("unchecked") - public final W withWidget(String widgetType) { - setType(widgetType); - return (W) this; - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SimpleWidget.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SimpleWidget.java deleted file mode 100644 index df914706596..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SimpleWidget.java +++ /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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import edu.wpi.first.networktables.GenericEntry; -import edu.wpi.first.networktables.NetworkTable; - -/** A Shuffleboard widget that handles a single data point such as a number or string. */ -public final class SimpleWidget extends ShuffleboardWidget implements AutoCloseable { - private String m_typeString = ""; - private GenericEntry m_entry; - - SimpleWidget(ShuffleboardContainer parent, String title) { - super(parent, title); - } - - /** - * Gets the NetworkTable entry that contains the data for this widget. - * - * @return The NetworkTable entry that contains the data for this widget. - */ - public GenericEntry getEntry() { - if (m_entry == null) { - forceGenerate(); - } - return m_entry; - } - - /** - * Gets the NetworkTable entry that contains the data for this widget. - * - * @param typeString NetworkTable type string - * @return The NetworkTable entry that contains the data for this widget. - */ - public GenericEntry getEntry(String typeString) { - if (m_entry == null) { - m_typeString = typeString; - forceGenerate(); - } - return m_entry; - } - - @Override - public void close() { - if (m_entry != null) { - m_entry.close(); - } - } - - @Override - public void buildInto(NetworkTable parentTable, NetworkTable metaTable) { - buildMetadata(metaTable); - if (m_entry == null) { - m_entry = parentTable.getTopic(getTitle()).getGenericEntry(m_typeString); - } - } - - private void forceGenerate() { - ShuffleboardContainer parent = getParent(); - while (parent instanceof ShuffleboardLayout layout) { - parent = layout.getParent(); - } - ShuffleboardTab tab = (ShuffleboardTab) parent; - tab.getRoot().update(); - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SuppliedValueWidget.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SuppliedValueWidget.java deleted file mode 100644 index 355f4836886..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/SuppliedValueWidget.java +++ /dev/null @@ -1,71 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import edu.wpi.first.networktables.BooleanPublisher; -import edu.wpi.first.networktables.BooleanTopic; -import edu.wpi.first.networktables.GenericPublisher; -import edu.wpi.first.networktables.NetworkTable; -import java.util.function.BiConsumer; -import java.util.function.Supplier; - -/** - * A Shuffleboard widget whose value is provided by user code. - * - * @param the type of values in the widget - */ -public final class SuppliedValueWidget extends ShuffleboardWidget> - implements AutoCloseable { - private final String m_typeString; - private final Supplier m_supplier; - private final BiConsumer m_setter; - private BooleanPublisher m_controllablePub; - private GenericPublisher m_entry; - - /** - * Package-private constructor for use by the Shuffleboard API. - * - * @param parent the parent container for the widget - * @param title the title of the widget - * @param typeString the NetworkTables string type - * @param supplier the supplier for values to place in the NetworkTable entry - * @param setter the function for placing values in the NetworkTable entry - */ - SuppliedValueWidget( - ShuffleboardContainer parent, - String title, - String typeString, - Supplier supplier, - BiConsumer setter) { - super(parent, title); - m_typeString = typeString; - m_supplier = supplier; - m_setter = setter; - } - - @Override - public void buildInto(NetworkTable parentTable, NetworkTable metaTable) { - buildMetadata(metaTable); - if (m_controllablePub == null) { - m_controllablePub = new BooleanTopic(metaTable.getTopic("Controllable")).publish(); - m_controllablePub.set(false); - } - - if (m_entry == null) { - m_entry = parentTable.getTopic(getTitle()).genericPublish(m_typeString); - } - m_setter.accept(m_entry, m_supplier.get()); - } - - @Override - public void close() { - if (m_controllablePub != null) { - m_controllablePub.close(); - } - if (m_entry != null) { - m_entry.close(); - } - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/WidgetType.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/WidgetType.java deleted file mode 100644 index 3033f8efc80..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/shuffleboard/WidgetType.java +++ /dev/null @@ -1,20 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -/** - * Represents the type of a widget in Shuffleboard. Using this is preferred over specifying raw - * strings, to avoid typos and having to know or look up the exact string name for a desired widget. - * - * @see BuiltInWidgets the built-in widget types - */ -public interface WidgetType { - /** - * Gets the string type of the widget as defined by that widget in Shuffleboard. - * - * @return The string type of the widget. - */ - String getWidgetName(); -} diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/MockActuatorSendable.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/MockActuatorSendable.java deleted file mode 100644 index a630c3e1afb..00000000000 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/MockActuatorSendable.java +++ /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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import edu.wpi.first.util.sendable.Sendable; -import edu.wpi.first.util.sendable.SendableBuilder; -import edu.wpi.first.util.sendable.SendableRegistry; - -/** A mock sendable that marks itself as an actuator. */ -public class MockActuatorSendable implements Sendable { - @SuppressWarnings("this-escape") - public MockActuatorSendable(String name) { - SendableRegistry.add(this, name); - } - - @Override - public void initSendable(SendableBuilder builder) { - builder.setActuator(true); - } -} diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/SendableCameraWrapperTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/SendableCameraWrapperTest.java deleted file mode 100644 index ed24453cbaa..00000000000 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/SendableCameraWrapperTest.java +++ /dev/null @@ -1,65 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import edu.wpi.first.networktables.NetworkTableInstance; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class SendableCameraWrapperTest { - NetworkTableInstance m_inst; - - @BeforeEach - void setup() { - m_inst = NetworkTableInstance.create(); - SendableCameraWrapper.clearWrappers(); - } - - @AfterEach - void tearDown() { - m_inst.close(); - } - - @Test - void testNullCameraName() { - assertThrows(NullPointerException.class, () -> SendableCameraWrapper.wrap(null, "")); - } - - @Test - void testEmptyCameraName() { - assertThrows(IllegalArgumentException.class, () -> SendableCameraWrapper.wrap("", "")); - } - - @Test - void testNullUrlArray() { - assertThrows( - NullPointerException.class, () -> SendableCameraWrapper.wrap("name", (String[]) null)); - } - - @Test - void testNullUrlInArray() { - assertThrows(NullPointerException.class, () -> SendableCameraWrapper.wrap("name", "url", null)); - } - - @Test - void testEmptyUrlArray() { - assertThrows(IllegalArgumentException.class, () -> SendableCameraWrapper.wrap("name")); - } - - @Test - void testUrlsAddedToNt() { - SendableCameraWrapper.wrap("name", "url1", "url2"); - assertArrayEquals( - new String[] {"url1", "url2"}, - NetworkTableInstance.getDefault() - .getEntry("/CameraPublisher/name/streams") - .getValue() - .getStringArray()); - } -} diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardInstanceTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardInstanceTest.java deleted file mode 100644 index 25b545b9713..00000000000 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardInstanceTest.java +++ /dev/null @@ -1,158 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import edu.wpi.first.networktables.GenericEntry; -import edu.wpi.first.networktables.NetworkTableEntry; -import edu.wpi.first.networktables.NetworkTableEvent.Kind; -import edu.wpi.first.networktables.NetworkTableInstance; -import edu.wpi.first.networktables.PubSubOption; -import edu.wpi.first.networktables.StringSubscriber; -import java.util.EnumSet; -import java.util.concurrent.atomic.AtomicInteger; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -class ShuffleboardInstanceTest { - private NetworkTableInstance m_ntInstance; - private ShuffleboardInstance m_shuffleboardInstance; - - @BeforeEach - void setupInstance() { - m_ntInstance = NetworkTableInstance.create(); - m_shuffleboardInstance = new ShuffleboardInstance(m_ntInstance); - } - - @AfterEach - void tearDownInstance() { - m_ntInstance.close(); - } - - @Test - void testPathFluent() { - GenericEntry entry = - m_shuffleboardInstance - .getTab("Tab Title") - .getLayout("Layout Title", "List Layout") - .add("Data", "string") - .withWidget("Text View") - .getEntry(); - - assertAll( - () -> assertEquals("string", entry.getString(null), "Wrong entry value"), - () -> - assertEquals( - "/Shuffleboard/Tab Title/Layout Title/Data", - entry.getTopic().getName(), - "Entry path generated incorrectly")); - } - - @Test - void testNestedLayoutsFluent() { - GenericEntry entry = - m_shuffleboardInstance - .getTab("Tab") - .getLayout("First", "List") - .getLayout("Second", "List") - .getLayout("Third", "List") - .getLayout("Fourth", "List") - .add("Value", "string") - .getEntry(); - - assertAll( - () -> assertEquals("string", entry.getString(null), "Wrong entry value"), - () -> - assertEquals( - "/Shuffleboard/Tab/First/Second/Third/Fourth/Value", - entry.getTopic().getName(), - "Entry path generated incorrectly")); - } - - @Test - void testNestedLayoutsOop() { - ShuffleboardTab tab = m_shuffleboardInstance.getTab("Tab"); - ShuffleboardLayout first = tab.getLayout("First", "List"); - ShuffleboardLayout second = first.getLayout("Second", "List"); - ShuffleboardLayout third = second.getLayout("Third", "List"); - ShuffleboardLayout fourth = third.getLayout("Fourth", "List"); - SimpleWidget widget = fourth.add("Value", "string"); - GenericEntry entry = widget.getEntry(); - - assertAll( - () -> assertEquals("string", entry.getString(null), "Wrong entry value"), - () -> - assertEquals( - "/Shuffleboard/Tab/First/Second/Third/Fourth/Value", - entry.getTopic().getName(), - "Entry path generated incorrectly")); - } - - @Test - void testLayoutTypeIsSet() { - String layoutType = "Type"; - m_shuffleboardInstance.getTab("Tab").getLayout("Title", layoutType); - m_shuffleboardInstance.update(); - NetworkTableEntry entry = - m_ntInstance.getEntry("/Shuffleboard/.metadata/Tab/Title/PreferredComponent"); - assertEquals(layoutType, entry.getString("Not Set"), "Layout type not set"); - } - - @Test - void testNestedActuatorWidgetsAreDisabled() { - m_shuffleboardInstance - .getTab("Tab") - .getLayout("Title", "Layout") - .add(new MockActuatorSendable("Actuator")); - NetworkTableEntry controllableEntry = - m_ntInstance.getEntry("/Shuffleboard/Tab/Title/Actuator/.controllable"); - - m_shuffleboardInstance.update(); - - // Note: we use the unsafe `getBoolean()` method because if the value is NOT a boolean, or if it - // is not present, then something has clearly gone very, very wrong - boolean controllable = controllableEntry.getValue().getBoolean(); - - // Sanity check - assertTrue(controllable, "The nested actuator widget should be enabled by default"); - m_shuffleboardInstance.disableActuatorWidgets(); - controllable = controllableEntry.getValue().getBoolean(); - assertFalse(controllable, "The nested actuator widget should have been disabled"); - } - - @Disabled("Fails often at counter assertion 'expected: <2> but was: <1>'") - @Test - void testDuplicateSelectTabs() { - int listener = 0; - AtomicInteger counter = new AtomicInteger(); - try (StringSubscriber subscriber = - m_ntInstance - .getStringTopic("/Shuffleboard/.metadata/Selected") - .subscribe("", PubSubOption.keepDuplicates(true))) { - listener = - m_ntInstance.addListener( - subscriber, - EnumSet.of(Kind.kValueAll, Kind.kImmediate), - event -> counter.incrementAndGet()); - - // There shouldn't be anything there - assertEquals(0, counter.get()); - - m_shuffleboardInstance.selectTab("tab1"); - m_shuffleboardInstance.selectTab("tab1"); - assertTrue(m_ntInstance.waitForListenerQueue(1.0), "Listener queue timed out!"); - assertEquals(2, counter.get()); - - } finally { - m_ntInstance.removeListener(listener); - } - } -} diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardTest.java deleted file mode 100644 index f4c8a8fbfd7..00000000000 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/ShuffleboardTest.java +++ /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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import static org.junit.jupiter.api.Assertions.assertSame; - -import edu.wpi.first.wpilibj.UtilityClassTest; -import org.junit.jupiter.api.Test; - -class ShuffleboardTest extends UtilityClassTest { - ShuffleboardTest() { - super(Shuffleboard.class); - } - - // Most relevant tests are in ShuffleboardTabTest - - @Test - void testTabObjectsCached() { - ShuffleboardTab tab1 = Shuffleboard.getTab("testTabObjectsCached"); - ShuffleboardTab tab2 = Shuffleboard.getTab("testTabObjectsCached"); - assertSame(tab1, tab2, "Tab objects were not cached"); - } -} diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/SuppliedValueWidgetTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/SuppliedValueWidgetTest.java deleted file mode 100644 index 794d155b1d9..00000000000 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/shuffleboard/SuppliedValueWidgetTest.java +++ /dev/null @@ -1,112 +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. - -package edu.wpi.first.wpilibj.shuffleboard; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import edu.wpi.first.networktables.NetworkTableEntry; -import edu.wpi.first.networktables.NetworkTableInstance; -import java.util.concurrent.atomic.AtomicInteger; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class SuppliedValueWidgetTest { - private NetworkTableInstance m_ntInstance; - private ShuffleboardInstance m_instance; - - @BeforeEach - void setup() { - m_ntInstance = NetworkTableInstance.create(); - m_instance = new ShuffleboardInstance(m_ntInstance); - } - - @AfterEach - void tearDown() { - m_ntInstance.close(); - } - - @Test - void testAddString() { - AtomicInteger count = new AtomicInteger(0); - m_instance.getTab("Tab").addString("Title", () -> Integer.toString(count.incrementAndGet())); - NetworkTableEntry entry = m_ntInstance.getEntry("/Shuffleboard/Tab/Title"); - - m_instance.update(); - assertEquals("1", entry.getString(null)); - - m_instance.update(); - assertEquals("2", entry.getString(null)); - } - - @Test - void testAddDouble() { - AtomicInteger num = new AtomicInteger(0); - m_instance.getTab("Tab").addNumber("Title", num::incrementAndGet); - NetworkTableEntry entry = m_ntInstance.getEntry("/Shuffleboard/Tab/Title"); - - m_instance.update(); - assertEquals(1, entry.getDouble(0)); - - m_instance.update(); - assertEquals(2, entry.getDouble(0)); - } - - @Test - void testAddBoolean() { - boolean[] bool = {false}; - m_instance.getTab("Tab").addBoolean("Title", () -> bool[0] = !bool[0]); - NetworkTableEntry entry = m_ntInstance.getEntry("/Shuffleboard/Tab/Title"); - - m_instance.update(); - assertTrue(entry.getBoolean(false)); - - m_instance.update(); - assertFalse(entry.getBoolean(true)); - } - - @Test - void testAddStringArray() { - String[] arr = {"foo", "bar"}; - m_instance.getTab("Tab").addStringArray("Title", () -> arr); - NetworkTableEntry entry = m_ntInstance.getEntry("/Shuffleboard/Tab/Title"); - - m_instance.update(); - assertArrayEquals(arr, entry.getStringArray(new String[0])); - } - - @Test - void testAddDoubleArray() { - double[] arr = {0, 1}; - m_instance.getTab("Tab").addDoubleArray("Title", () -> arr); - NetworkTableEntry entry = m_ntInstance.getEntry("/Shuffleboard/Tab/Title"); - - m_instance.update(); - assertArrayEquals(arr, entry.getDoubleArray(new double[0])); - } - - @Test - void testAddBooleanArray() { - boolean[] arr = {true, false}; - m_instance.getTab("Tab").addBooleanArray("Title", () -> arr); - NetworkTableEntry entry = m_ntInstance.getEntry("/Shuffleboard/Tab/Title"); - - m_instance.update(); - assertArrayEquals(arr, entry.getBooleanArray(new boolean[0])); - } - - @Test - void testAddRawBytes() { - byte[] arr = {0, 1, 2, 3}; - m_instance.getTab("Tab").addRaw("Title", () -> arr); - NetworkTableEntry entry = m_ntInstance.getEntry("/Shuffleboard/Tab/Title"); - - m_instance.update(); - assertArrayEquals(arr, entry.getRaw(new byte[0])); - } -} 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 5fab0669611..ac667693ce7 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 @@ -68,7 +68,6 @@ "tags": [ "Hardware", "Joystick", - "Shuffleboard", "Pneumatics" ], "foldername": "solenoid", @@ -108,8 +107,7 @@ "tags": [ "Hardware", "Ultrasonic", - "SmartDashboard", - "Shuffleboard" + "SmartDashboard" ], "foldername": "ultrasonic", "gradlebase": "java", @@ -308,22 +306,6 @@ "mainclass": "Main", "commandversion": 2 }, - { - "name": "Shuffleboard", - "description": "Present various data via the Shuffleboard API.", - "tags": [ - "Basic Robot", - "Differential Drive", - "Elevator", - "Analog", - "Encoder", - "Shuffleboard" - ], - "foldername": "shuffleboard", - "gradlebase": "java", - "mainclass": "Main", - "commandversion": 2 - }, { "name": "'Traditional' Hatchbot", "description": "A fully-functional command-based hatchbot for the 2019 game, written in the 'traditional' style, i.e. commands are given their own classes.", @@ -333,7 +315,6 @@ "Differential Drive", "Encoder", "Pneumatics", - "Shuffleboard", "Sendable", "DataLog", "XboxController" @@ -352,7 +333,6 @@ "Differential Drive", "Encoder", "Pneumatics", - "Shuffleboard", "Sendable", "DataLog", "PS4Controller" diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbotinlined/RobotContainer.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbotinlined/RobotContainer.java index 2d7cedf4682..f4454aa2de5 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbotinlined/RobotContainer.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbotinlined/RobotContainer.java @@ -9,11 +9,9 @@ import edu.wpi.first.wpilibj.examples.hatchbotinlined.commands.Autos; import edu.wpi.first.wpilibj.examples.hatchbotinlined.subsystems.DriveSubsystem; import edu.wpi.first.wpilibj.examples.hatchbotinlined.subsystems.HatchSubsystem; -import edu.wpi.first.wpilibj.shuffleboard.EventImportance; -import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; import edu.wpi.first.wpilibj.smartdashboard.SendableChooser; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.CommandScheduler; import edu.wpi.first.wpilibj2.command.Commands; import edu.wpi.first.wpilibj2.command.button.CommandPS4Controller; @@ -64,28 +62,11 @@ public RobotContainer() { m_chooser.addOption("Complex Auto", m_complexAuto); // Put the chooser on the dashboard - Shuffleboard.getTab("Autonomous").add(m_chooser); + SmartDashboard.putData("Autonomous", m_chooser); // Put subsystems to dashboard. - Shuffleboard.getTab("Drivetrain").add(m_robotDrive); - Shuffleboard.getTab("HatchSubsystem").add(m_hatchSubsystem); - - // Set the scheduler to log Shuffleboard events for command initialize, interrupt, finish - CommandScheduler.getInstance() - .onCommandInitialize( - command -> - Shuffleboard.addEventMarker( - "Command initialized", command.getName(), EventImportance.kNormal)); - CommandScheduler.getInstance() - .onCommandInterrupt( - command -> - Shuffleboard.addEventMarker( - "Command interrupted", command.getName(), EventImportance.kNormal)); - CommandScheduler.getInstance() - .onCommandFinish( - command -> - Shuffleboard.addEventMarker( - "Command finished", command.getName(), EventImportance.kNormal)); + SmartDashboard.putData("Drivetrain", m_robotDrive); + SmartDashboard.putData("HatchSubsystem", m_hatchSubsystem); } /** diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbottraditional/RobotContainer.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbottraditional/RobotContainer.java index 5bf05b4dd4b..24af4abc2f2 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbottraditional/RobotContainer.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbottraditional/RobotContainer.java @@ -17,11 +17,9 @@ import edu.wpi.first.wpilibj.examples.hatchbottraditional.commands.ReleaseHatch; import edu.wpi.first.wpilibj.examples.hatchbottraditional.subsystems.DriveSubsystem; import edu.wpi.first.wpilibj.examples.hatchbottraditional.subsystems.HatchSubsystem; -import edu.wpi.first.wpilibj.shuffleboard.EventImportance; -import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; import edu.wpi.first.wpilibj.smartdashboard.SendableChooser; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj2.command.Command; -import edu.wpi.first.wpilibj2.command.CommandScheduler; import edu.wpi.first.wpilibj2.command.button.JoystickButton; /** @@ -71,32 +69,10 @@ public RobotContainer() { m_chooser.addOption("Complex Auto", m_complexAuto); // Put the chooser on the dashboard - Shuffleboard.getTab("Autonomous").add(m_chooser); + SmartDashboard.putData("Autonomous", m_chooser); // Put subsystems to dashboard. - Shuffleboard.getTab("Drivetrain").add(m_robotDrive); - Shuffleboard.getTab("HatchSubsystem").add(m_hatchSubsystem); - - // Log Shuffleboard events for command initialize, execute, finish, interrupt - CommandScheduler.getInstance() - .onCommandInitialize( - command -> - Shuffleboard.addEventMarker( - "Command initialized", command.getName(), EventImportance.kNormal)); - CommandScheduler.getInstance() - .onCommandExecute( - command -> - Shuffleboard.addEventMarker( - "Command executed", command.getName(), EventImportance.kNormal)); - CommandScheduler.getInstance() - .onCommandFinish( - command -> - Shuffleboard.addEventMarker( - "Command finished", command.getName(), EventImportance.kNormal)); - CommandScheduler.getInstance() - .onCommandInterrupt( - command -> - Shuffleboard.addEventMarker( - "Command interrupted", command.getName(), EventImportance.kNormal)); + SmartDashboard.putData("Drivetrain", m_robotDrive); + SmartDashboard.putData("HatchSubsystem", m_hatchSubsystem); } /** diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/shuffleboard/Main.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/shuffleboard/Main.java deleted file mode 100644 index 8a7a1c82c75..00000000000 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/shuffleboard/Main.java +++ /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. - -package edu.wpi.first.wpilibj.examples.shuffleboard; - -import edu.wpi.first.wpilibj.RobotBase; - -/** - * Do NOT add any static variables to this class, or any initialization at all. Unless you know what - * you are doing, do not modify this file except to change the parameter class to the startRobot - * call. - */ -public final class Main { - private Main() {} - - /** - * Main initialization function. Do not perform any initialization here. - * - *

If you change your main robot class, change the parameter type. - */ - public static void main(String... args) { - RobotBase.startRobot(Robot::new); - } -} diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/shuffleboard/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/shuffleboard/Robot.java deleted file mode 100644 index 8825b687444..00000000000 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/shuffleboard/Robot.java +++ /dev/null @@ -1,66 +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. - -package edu.wpi.first.wpilibj.examples.shuffleboard; - -import edu.wpi.first.networktables.GenericEntry; -import edu.wpi.first.util.sendable.SendableRegistry; -import edu.wpi.first.wpilibj.AnalogPotentiometer; -import edu.wpi.first.wpilibj.Encoder; -import edu.wpi.first.wpilibj.TimedRobot; -import edu.wpi.first.wpilibj.drive.DifferentialDrive; -import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax; -import edu.wpi.first.wpilibj.shuffleboard.BuiltInLayouts; -import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; -import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardLayout; -import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardTab; - -public class Robot extends TimedRobot { - private final PWMSparkMax m_leftDriveMotor = new PWMSparkMax(0); - private final PWMSparkMax m_rightDriveMotor = new PWMSparkMax(1); - private final DifferentialDrive m_tankDrive = - new DifferentialDrive(m_leftDriveMotor::set, m_rightDriveMotor::set); - private final Encoder m_leftEncoder = new Encoder(0, 1); - private final Encoder m_rightEncoder = new Encoder(2, 3); - - private final PWMSparkMax m_elevatorMotor = new PWMSparkMax(2); - private final AnalogPotentiometer m_elevatorPot = new AnalogPotentiometer(0); - private final GenericEntry m_maxSpeed; - - /** Called once at the beginning of the robot program. */ - public Robot() { - SendableRegistry.addChild(m_tankDrive, m_leftDriveMotor); - SendableRegistry.addChild(m_tankDrive, m_rightDriveMotor); - - // Add a 'max speed' widget to a tab named 'Configuration', using a number slider - // The widget will be placed in the second column and row and will be TWO columns wide - m_maxSpeed = - Shuffleboard.getTab("Configuration") - .add("Max Speed", 1) - .withWidget("Number Slider") - .withPosition(1, 1) - .withSize(2, 1) - .getEntry(); - - // Add the tank drive and encoders to a 'Drivebase' tab - ShuffleboardTab driveBaseTab = Shuffleboard.getTab("Drivebase"); - driveBaseTab.add("Tank Drive", m_tankDrive); - // Put both encoders in a list layout - ShuffleboardLayout encoders = - driveBaseTab.getLayout("Encoders", BuiltInLayouts.kList).withPosition(0, 0).withSize(2, 2); - encoders.add("Left Encoder", m_leftEncoder); - encoders.add("Right Encoder", m_rightEncoder); - - // Add the elevator motor and potentiometer to an 'Elevator' tab - ShuffleboardTab elevatorTab = Shuffleboard.getTab("Elevator"); - elevatorTab.add("Motor", m_elevatorMotor); - elevatorTab.add("Potentiometer", m_elevatorPot); - } - - @Override - public void autonomousInit() { - // Read the value of the 'max speed' widget from the dashboard - m_tankDrive.setMaxOutput(m_maxSpeed.getDouble(1.0)); - } -} diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java index d4346f02bc7..babff17e808 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/solenoid/Robot.java @@ -10,8 +10,7 @@ import edu.wpi.first.wpilibj.PneumaticsModuleType; import edu.wpi.first.wpilibj.Solenoid; import edu.wpi.first.wpilibj.TimedRobot; -import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; -import edu.wpi.first.wpilibj.shuffleboard.ShuffleboardTab; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; /** * This is a sample program showing the use of the solenoid classes during operator control. Three @@ -46,29 +45,28 @@ public class Robot extends TimedRobot { /** Called once at the beginning of the robot program. */ public Robot() { - // Publish elements to shuffleboard. - ShuffleboardTab tab = Shuffleboard.getTab("Pneumatics"); - tab.add("Single Solenoid", m_solenoid); - tab.add("Double Solenoid", m_doubleSolenoid); - tab.add("Compressor", m_compressor); + // Publish elements to dashboard. + SmartDashboard.putData("Single Solenoid", m_solenoid); + SmartDashboard.putData("Double Solenoid", m_doubleSolenoid); + SmartDashboard.putData("Compressor", m_compressor); + } - // Also publish some raw data + @SuppressWarnings("PMD.UnconditionalIfStatement") + @Override + public void teleopPeriodic() { + // Publish some raw data // Get the pressure (in PSI) from the analog sensor connected to the PH. // This function is supported only on the PH! // On a PCM, this function will return 0. - tab.addDouble("PH Pressure [PSI]", m_compressor::getPressure); + SmartDashboard.putNumber("PH Pressure [PSI]", m_compressor.getPressure()); // Get compressor current draw. - tab.addDouble("Compressor Current", m_compressor::getCurrent); + SmartDashboard.putNumber("Compressor Current", m_compressor.getCurrent()); // Get whether the compressor is active. - tab.addBoolean("Compressor Active", m_compressor::isEnabled); + SmartDashboard.putBoolean("Compressor Active", m_compressor.isEnabled()); // Get the digital pressure switch connected to the PCM/PH. // The switch is open when the pressure is over ~120 PSI. - tab.addBoolean("Pressure Switch", m_compressor::getPressureSwitchValue); - } + SmartDashboard.putBoolean("Pressure Switch", m_compressor.getPressureSwitchValue()); - @SuppressWarnings("PMD.UnconditionalIfStatement") - @Override - public void teleopPeriodic() { /* * The output of GetRawButton is true/false depending on whether * the button is pressed; Set takes a boolean for whether diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/ultrasonic/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/ultrasonic/Robot.java index 602e58abe5b..8727f92ff42 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/ultrasonic/Robot.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/ultrasonic/Robot.java @@ -6,7 +6,6 @@ import edu.wpi.first.wpilibj.TimedRobot; import edu.wpi.first.wpilibj.Ultrasonic; -import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; /** @@ -21,7 +20,7 @@ public class Robot extends TimedRobot { public Robot() { // Add the ultrasonic on the "Sensors" tab of the dashboard // Data will update automatically - Shuffleboard.getTab("Sensors").add(m_rangeFinder); + SmartDashboard.putData("Sensors", m_rangeFinder); } @Override From eee30c49e23eca1d4afcbf6dfa295a4de3b430ef Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 25 Jan 2025 10:52:19 -0800 Subject: [PATCH 5/6] [wpilib] Remove LiveWindow (#7733) This will be replaced by a different mechanism, but removing it eases the initial implementation burden of a new Telemetry/Sendable framework. --- .../logging/LogBackedSendableBuilder.java | 5 - gradle.properties | 2 +- .../wpilibj2/command/CommandScheduler.java | 11 +- .../first/wpilibj2/command/SubsystemBase.java | 6 +- .../cpp/frc2/command/CommandScheduler.cpp | 11 +- .../native/cpp/frc2/command/SubsystemBase.cpp | 6 +- wpilibc/src/main/native/cpp/ADXL345_I2C.cpp | 2 +- .../main/native/cpp/AnalogAccelerometer.cpp | 4 +- wpilibc/src/main/native/cpp/AnalogEncoder.cpp | 4 +- wpilibc/src/main/native/cpp/AnalogInput.cpp | 2 +- .../main/native/cpp/AnalogPotentiometer.cpp | 4 +- wpilibc/src/main/native/cpp/AnalogTrigger.cpp | 4 +- wpilibc/src/main/native/cpp/Compressor.cpp | 2 +- wpilibc/src/main/native/cpp/Counter.cpp | 2 +- wpilibc/src/main/native/cpp/DigitalInput.cpp | 2 +- wpilibc/src/main/native/cpp/DigitalOutput.cpp | 2 +- .../src/main/native/cpp/DoubleSolenoid.cpp | 5 +- wpilibc/src/main/native/cpp/DutyCycle.cpp | 2 +- .../src/main/native/cpp/DutyCycleEncoder.cpp | 4 +- wpilibc/src/main/native/cpp/Encoder.cpp | 2 +- .../main/native/cpp/IterativeRobotBase.cpp | 27 -- wpilibc/src/main/native/cpp/PWM.cpp | 3 +- .../src/main/native/cpp/PowerDistribution.cpp | 4 +- wpilibc/src/main/native/cpp/SharpIR.cpp | 2 +- wpilibc/src/main/native/cpp/Solenoid.cpp | 5 +- wpilibc/src/main/native/cpp/Ultrasonic.cpp | 2 +- .../cpp/counter/ExternalDirectionCounter.cpp | 2 +- .../main/native/cpp/counter/Tachometer.cpp | 2 +- .../main/native/cpp/counter/UpDownCounter.cpp | 2 +- .../native/cpp/drive/DifferentialDrive.cpp | 3 +- .../main/native/cpp/drive/MecanumDrive.cpp | 3 +- .../main/native/cpp/livewindow/LiveWindow.cpp | 230 ---------------- .../cpp/motorcontrol/MotorControllerGroup.cpp | 1 - .../cpp/motorcontrol/NidecBrushless.cpp | 3 +- .../cpp/motorcontrol/PWMMotorController.cpp | 3 +- .../smartdashboard/SendableBuilderImpl.cpp | 18 -- wpilibc/src/main/native/cppcs/RobotBase.cpp | 4 - .../native/include/frc/IterativeRobotBase.h | 14 - wpilibc/src/main/native/include/frc/PWM.h | 1 - .../include/frc/livewindow/LiveWindow.h | 90 ------- .../frc/smartdashboard/SendableBuilderImpl.h | 14 - .../src/test/native/cpp/TimedRobotTest.cpp | 16 +- .../templates/robotbaseskeleton/cpp/Robot.cpp | 3 - .../cpp/templates/timeslice/cpp/Robot.cpp | 5 - .../templates/timesliceskeleton/cpp/Robot.cpp | 6 - .../edu/wpi/first/wpilibj/ADXL345_I2C.java | 2 +- .../first/wpilibj/AnalogAccelerometer.java | 2 +- .../edu/wpi/first/wpilibj/AnalogEncoder.java | 2 +- .../edu/wpi/first/wpilibj/AnalogGyro.java | 2 +- .../edu/wpi/first/wpilibj/AnalogInput.java | 2 +- .../first/wpilibj/AnalogPotentiometer.java | 2 +- .../edu/wpi/first/wpilibj/AnalogTrigger.java | 4 +- .../edu/wpi/first/wpilibj/Compressor.java | 2 +- .../java/edu/wpi/first/wpilibj/Counter.java | 2 +- .../edu/wpi/first/wpilibj/DigitalInput.java | 2 +- .../edu/wpi/first/wpilibj/DigitalOutput.java | 2 +- .../edu/wpi/first/wpilibj/DoubleSolenoid.java | 3 +- .../java/edu/wpi/first/wpilibj/DutyCycle.java | 2 +- .../wpi/first/wpilibj/DutyCycleEncoder.java | 2 +- .../java/edu/wpi/first/wpilibj/Encoder.java | 2 +- .../wpi/first/wpilibj/IterativeRobotBase.java | 45 +--- .../main/java/edu/wpi/first/wpilibj/PWM.java | 7 +- .../wpi/first/wpilibj/PowerDistribution.java | 4 +- .../java/edu/wpi/first/wpilibj/RobotBase.java | 3 - .../java/edu/wpi/first/wpilibj/SharpIR.java | 2 +- .../java/edu/wpi/first/wpilibj/Solenoid.java | 3 +- .../edu/wpi/first/wpilibj/Ultrasonic.java | 2 +- .../counter/ExternalDirectionCounter.java | 2 +- .../wpi/first/wpilibj/counter/Tachometer.java | 2 +- .../first/wpilibj/counter/UpDownCounter.java | 2 +- .../wpilibj/drive/DifferentialDrive.java | 3 +- .../wpi/first/wpilibj/drive/MecanumDrive.java | 3 +- .../first/wpilibj/livewindow/LiveWindow.java | 247 ------------------ .../motorcontrol/MotorControllerGroup.java | 3 +- .../wpilibj/motorcontrol/NidecBrushless.java | 3 +- .../motorcontrol/PWMMotorController.java | 3 +- .../smartdashboard/SendableBuilderImpl.java | 34 --- .../edu/wpi/first/wpilibj/TimedRobotTest.java | 17 +- .../wpilibj/livewindow/LiveWindowTest.java | 14 - .../wpilibj/templates/timeslice/Robot.java | 5 - .../templates/timesliceskeleton/Robot.java | 5 - .../math/controller/BangBangController.java | 2 +- .../first/math/controller/PIDController.java | 2 +- .../first/util/sendable/SendableBuilder.java | 8 - .../first/util/sendable/SendableRegistry.java | 232 +--------------- .../native/cpp/sendable/SendableRegistry.cpp | 101 ------- .../include/wpi/sendable/SendableBuilder.h | 8 - .../include/wpi/sendable/SendableRegistry.h | 101 +------ 88 files changed, 85 insertions(+), 1356 deletions(-) delete mode 100644 wpilibc/src/main/native/cpp/livewindow/LiveWindow.cpp delete mode 100644 wpilibc/src/main/native/include/frc/livewindow/LiveWindow.h delete mode 100644 wpilibj/src/main/java/edu/wpi/first/wpilibj/livewindow/LiveWindow.java delete mode 100644 wpilibj/src/test/java/edu/wpi/first/wpilibj/livewindow/LiveWindowTest.java diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/LogBackedSendableBuilder.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/LogBackedSendableBuilder.java index 5de5756ff4f..4b93a88ee55 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/LogBackedSendableBuilder.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/LogBackedSendableBuilder.java @@ -43,11 +43,6 @@ public void setActuator(boolean value) { // ignore } - @Override - public void setSafeState(Runnable func) { - // ignore - } - @Override public void addBooleanProperty(String key, BooleanSupplier getter, BooleanConsumer setter) { m_updates.add(() -> m_backend.log(key, getter.getAsBoolean())); diff --git a/gradle.properties b/gradle.properties index ac38aaaad1c..1e28aedd1be 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ -org.gradle.jvmargs=-Xmx2g +org.gradle.jvmargs=-Xmx4g org.ysb33r.gradle.doxygen.download.url=https://frcmaven.wpi.edu/artifactory/generic-release-mirror/doxygen diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandScheduler.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandScheduler.java index 15babf85bbf..34319caa079 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandScheduler.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandScheduler.java @@ -18,7 +18,6 @@ import edu.wpi.first.wpilibj.TimedRobot; import edu.wpi.first.wpilibj.Watchdog; import edu.wpi.first.wpilibj.event.EventLoop; -import edu.wpi.first.wpilibj.livewindow.LiveWindow; import edu.wpi.first.wpilibj2.command.Command.InterruptionBehavior; import java.io.PrintWriter; import java.io.StringWriter; @@ -101,13 +100,7 @@ public static synchronized CommandScheduler getInstance() { CommandScheduler() { HAL.report(tResourceType.kResourceType_Command, tInstances.kCommand2_Scheduler); - SendableRegistry.addLW(this, "Scheduler"); - LiveWindow.setEnabledListener( - () -> { - disable(); - cancelAll(); - }); - LiveWindow.setDisabledListener(this::enable); + SendableRegistry.add(this, "Scheduler"); } /** @@ -123,8 +116,6 @@ public void setPeriod(double period) { @Override public void close() { SendableRegistry.remove(this); - LiveWindow.setEnabledListener(null); - LiveWindow.setDisabledListener(null); } /** diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SubsystemBase.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SubsystemBase.java index 3a024e5f665..0ab58cd4fbe 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SubsystemBase.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/SubsystemBase.java @@ -20,7 +20,7 @@ public abstract class SubsystemBase implements Subsystem, Sendable { public SubsystemBase() { String name = this.getClass().getSimpleName(); name = name.substring(name.lastIndexOf('.') + 1); - SendableRegistry.addLW(this, name, name); + SendableRegistry.add(this, name, name); CommandScheduler.getInstance().registerSubsystem(this); } @@ -31,7 +31,7 @@ public SubsystemBase() { */ @SuppressWarnings("this-escape") public SubsystemBase(String name) { - SendableRegistry.addLW(this, name, name); + SendableRegistry.add(this, name, name); CommandScheduler.getInstance().registerSubsystem(this); } @@ -79,7 +79,7 @@ public void setSubsystem(String subsystem) { * @param child sendable */ public void addChild(String name, Sendable child) { - SendableRegistry.addLW(child, getSubsystem(), name); + SendableRegistry.add(child, getSubsystem(), name); } @Override diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandScheduler.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandScheduler.cpp index 369e14367bc..b077de5e538 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandScheduler.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandScheduler.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -72,19 +71,11 @@ CommandScheduler::CommandScheduler() }) { HAL_Report(HALUsageReporting::kResourceType_Command, HALUsageReporting::kCommand2_Scheduler); - wpi::SendableRegistry::AddLW(this, "Scheduler"); - frc::LiveWindow::SetEnabledCallback([this] { - this->Disable(); - this->CancelAll(); - }); - frc::LiveWindow::SetDisabledCallback([this] { this->Enable(); }); + wpi::SendableRegistry::Add(this, "Scheduler"); } CommandScheduler::~CommandScheduler() { wpi::SendableRegistry::Remove(this); - frc::LiveWindow::SetEnabledCallback(nullptr); - frc::LiveWindow::SetDisabledCallback(nullptr); - std::unique_ptr().swap(m_impl); } diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/SubsystemBase.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/SubsystemBase.cpp index e0638263642..d66b6bfc818 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/SubsystemBase.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/SubsystemBase.cpp @@ -15,12 +15,12 @@ using namespace frc2; SubsystemBase::SubsystemBase() { - wpi::SendableRegistry::AddLW(this, GetTypeName(*this)); + wpi::SendableRegistry::Add(this, GetTypeName(*this)); CommandScheduler::GetInstance().RegisterSubsystem({this}); } SubsystemBase::SubsystemBase(std::string_view name) { - wpi::SendableRegistry::AddLW(this, name); + wpi::SendableRegistry::Add(this, name); CommandScheduler::GetInstance().RegisterSubsystem({this}); } @@ -71,5 +71,5 @@ void SubsystemBase::SetSubsystem(std::string_view name) { } void SubsystemBase::AddChild(std::string name, wpi::Sendable* child) { - wpi::SendableRegistry::AddLW(child, GetSubsystem(), name); + wpi::SendableRegistry::Add(child, GetSubsystem(), name); } diff --git a/wpilibc/src/main/native/cpp/ADXL345_I2C.cpp b/wpilibc/src/main/native/cpp/ADXL345_I2C.cpp index a23846d8291..1fdf71ed373 100644 --- a/wpilibc/src/main/native/cpp/ADXL345_I2C.cpp +++ b/wpilibc/src/main/native/cpp/ADXL345_I2C.cpp @@ -30,7 +30,7 @@ ADXL345_I2C::ADXL345_I2C(I2C::Port port, Range range, int deviceAddress) HAL_Report(HALUsageReporting::kResourceType_ADXL345, HALUsageReporting::kADXL345_I2C, 0); - wpi::SendableRegistry::AddLW(this, "ADXL345_I2C", port); + wpi::SendableRegistry::Add(this, "ADXL345_I2C", port); } I2C::Port ADXL345_I2C::GetI2CPort() const { diff --git a/wpilibc/src/main/native/cpp/AnalogAccelerometer.cpp b/wpilibc/src/main/native/cpp/AnalogAccelerometer.cpp index ca8af7d5d9d..70d91fcef94 100644 --- a/wpilibc/src/main/native/cpp/AnalogAccelerometer.cpp +++ b/wpilibc/src/main/native/cpp/AnalogAccelerometer.cpp @@ -56,6 +56,6 @@ void AnalogAccelerometer::InitAccelerometer() { HAL_Report(HALUsageReporting::kResourceType_Accelerometer, m_analogInput->GetChannel() + 1); - wpi::SendableRegistry::AddLW(this, "Accelerometer", - m_analogInput->GetChannel()); + wpi::SendableRegistry::Add(this, "Accelerometer", + m_analogInput->GetChannel()); } diff --git a/wpilibc/src/main/native/cpp/AnalogEncoder.cpp b/wpilibc/src/main/native/cpp/AnalogEncoder.cpp index 13a788788cb..c251ebcf5eb 100644 --- a/wpilibc/src/main/native/cpp/AnalogEncoder.cpp +++ b/wpilibc/src/main/native/cpp/AnalogEncoder.cpp @@ -67,8 +67,8 @@ void AnalogEncoder::Init(double fullRange, double expectedZero) { m_fullRange = fullRange; m_expectedZero = expectedZero; - wpi::SendableRegistry::AddLW(this, "Analog Encoder", - m_analogInput->GetChannel()); + wpi::SendableRegistry::Add(this, "Analog Encoder", + m_analogInput->GetChannel()); } double AnalogEncoder::Get() const { diff --git a/wpilibc/src/main/native/cpp/AnalogInput.cpp b/wpilibc/src/main/native/cpp/AnalogInput.cpp index 188ddb74994..84f168e18e3 100644 --- a/wpilibc/src/main/native/cpp/AnalogInput.cpp +++ b/wpilibc/src/main/native/cpp/AnalogInput.cpp @@ -35,7 +35,7 @@ AnalogInput::AnalogInput(int channel) { HAL_Report(HALUsageReporting::kResourceType_AnalogChannel, channel + 1); - wpi::SendableRegistry::AddLW(this, "AnalogInput", channel); + wpi::SendableRegistry::Add(this, "AnalogInput", channel); } int AnalogInput::GetValue() const { diff --git a/wpilibc/src/main/native/cpp/AnalogPotentiometer.cpp b/wpilibc/src/main/native/cpp/AnalogPotentiometer.cpp index 31432e9681c..2855464bd64 100644 --- a/wpilibc/src/main/native/cpp/AnalogPotentiometer.cpp +++ b/wpilibc/src/main/native/cpp/AnalogPotentiometer.cpp @@ -33,8 +33,8 @@ AnalogPotentiometer::AnalogPotentiometer(std::shared_ptr input, : m_analog_input(std::move(input)), m_fullRange(fullRange), m_offset(offset) { - wpi::SendableRegistry::AddLW(this, "AnalogPotentiometer", - m_analog_input->GetChannel()); + wpi::SendableRegistry::Add(this, "AnalogPotentiometer", + m_analog_input->GetChannel()); } double AnalogPotentiometer::Get() const { diff --git a/wpilibc/src/main/native/cpp/AnalogTrigger.cpp b/wpilibc/src/main/native/cpp/AnalogTrigger.cpp index 6759b61dde6..ca441103a04 100644 --- a/wpilibc/src/main/native/cpp/AnalogTrigger.cpp +++ b/wpilibc/src/main/native/cpp/AnalogTrigger.cpp @@ -38,7 +38,7 @@ AnalogTrigger::AnalogTrigger(std::shared_ptr input) int index = GetIndex(); HAL_Report(HALUsageReporting::kResourceType_AnalogTrigger, index + 1); - wpi::SendableRegistry::AddLW(this, "AnalogTrigger", index); + wpi::SendableRegistry::Add(this, "AnalogTrigger", index); } AnalogTrigger::AnalogTrigger(DutyCycle& input) @@ -55,7 +55,7 @@ AnalogTrigger::AnalogTrigger(std::shared_ptr input) int index = GetIndex(); HAL_Report(HALUsageReporting::kResourceType_AnalogTrigger, index + 1); - wpi::SendableRegistry::AddLW(this, "AnalogTrigger", index); + wpi::SendableRegistry::Add(this, "AnalogTrigger", index); } void AnalogTrigger::SetLimitsVoltage(double lower, double upper) { diff --git a/wpilibc/src/main/native/cpp/Compressor.cpp b/wpilibc/src/main/native/cpp/Compressor.cpp index 1306561fcba..bb9a62fbd18 100644 --- a/wpilibc/src/main/native/cpp/Compressor.cpp +++ b/wpilibc/src/main/native/cpp/Compressor.cpp @@ -25,7 +25,7 @@ Compressor::Compressor(int module, PneumaticsModuleType moduleType) m_module->EnableCompressorDigital(); HAL_Report(HALUsageReporting::kResourceType_Compressor, module + 1); - wpi::SendableRegistry::AddLW(this, "Compressor", module); + wpi::SendableRegistry::Add(this, "Compressor", module); } Compressor::Compressor(PneumaticsModuleType moduleType) diff --git a/wpilibc/src/main/native/cpp/Counter.cpp b/wpilibc/src/main/native/cpp/Counter.cpp index 32523c245a2..2021443f5ad 100644 --- a/wpilibc/src/main/native/cpp/Counter.cpp +++ b/wpilibc/src/main/native/cpp/Counter.cpp @@ -27,7 +27,7 @@ Counter::Counter(Mode mode) { SetMaxPeriod(0.5_s); HAL_Report(HALUsageReporting::kResourceType_Counter, m_index + 1, mode + 1); - wpi::SendableRegistry::AddLW(this, "Counter", m_index); + wpi::SendableRegistry::Add(this, "Counter", m_index); } Counter::Counter(int channel) : Counter(kTwoPulse) { diff --git a/wpilibc/src/main/native/cpp/DigitalInput.cpp b/wpilibc/src/main/native/cpp/DigitalInput.cpp index f6c2d8b03c6..4c1474f0d96 100644 --- a/wpilibc/src/main/native/cpp/DigitalInput.cpp +++ b/wpilibc/src/main/native/cpp/DigitalInput.cpp @@ -32,7 +32,7 @@ DigitalInput::DigitalInput(int channel) { FRC_CheckErrorStatus(status, "Channel {}", channel); HAL_Report(HALUsageReporting::kResourceType_DigitalInput, channel + 1); - wpi::SendableRegistry::AddLW(this, "DigitalInput", channel); + wpi::SendableRegistry::Add(this, "DigitalInput", channel); } bool DigitalInput::Get() const { diff --git a/wpilibc/src/main/native/cpp/DigitalOutput.cpp b/wpilibc/src/main/native/cpp/DigitalOutput.cpp index ee54bb4294d..3a2ec092cae 100644 --- a/wpilibc/src/main/native/cpp/DigitalOutput.cpp +++ b/wpilibc/src/main/native/cpp/DigitalOutput.cpp @@ -33,7 +33,7 @@ DigitalOutput::DigitalOutput(int channel) { FRC_CheckErrorStatus(status, "Channel {}", channel); HAL_Report(HALUsageReporting::kResourceType_DigitalOutput, channel + 1); - wpi::SendableRegistry::AddLW(this, "DigitalOutput", channel); + wpi::SendableRegistry::Add(this, "DigitalOutput", channel); } DigitalOutput::~DigitalOutput() { diff --git a/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp b/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp index c111622545c..f87d3ebeb7c 100644 --- a/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp +++ b/wpilibc/src/main/native/cpp/DoubleSolenoid.cpp @@ -55,8 +55,8 @@ DoubleSolenoid::DoubleSolenoid(int module, PneumaticsModuleType moduleType, HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_reverseChannel + 1, m_module->GetModuleNumber() + 1); - wpi::SendableRegistry::AddLW(this, "DoubleSolenoid", - m_module->GetModuleNumber(), m_forwardChannel); + wpi::SendableRegistry::Add(this, "DoubleSolenoid", + m_module->GetModuleNumber(), m_forwardChannel); } DoubleSolenoid::DoubleSolenoid(PneumaticsModuleType moduleType, @@ -129,7 +129,6 @@ bool DoubleSolenoid::IsRevSolenoidDisabled() const { void DoubleSolenoid::InitSendable(wpi::SendableBuilder& builder) { builder.SetSmartDashboardType("Double Solenoid"); builder.SetActuator(true); - builder.SetSafeState([=, this] { Set(kOff); }); builder.AddSmallStringProperty( "Value", [=, this](wpi::SmallVectorImpl& buf) -> std::string_view { diff --git a/wpilibc/src/main/native/cpp/DutyCycle.cpp b/wpilibc/src/main/native/cpp/DutyCycle.cpp index 6045e3cd71f..1a5c23dddc8 100644 --- a/wpilibc/src/main/native/cpp/DutyCycle.cpp +++ b/wpilibc/src/main/native/cpp/DutyCycle.cpp @@ -34,7 +34,7 @@ void DutyCycle::InitDutyCycle() { &status); FRC_CheckErrorStatus(status, "Channel {}", GetSourceChannel()); HAL_Report(HALUsageReporting::kResourceType_DutyCycle, m_channel + 1); - wpi::SendableRegistry::AddLW(this, "Duty Cycle", m_channel); + wpi::SendableRegistry::Add(this, "Duty Cycle", m_channel); } int DutyCycle::GetFPGAIndex() const { diff --git a/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp b/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp index e94c6a331be..5f1eabd60c1 100644 --- a/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp +++ b/wpilibc/src/main/native/cpp/DutyCycleEncoder.cpp @@ -74,8 +74,8 @@ void DutyCycleEncoder::Init(double fullRange, double expectedZero) { m_fullRange = fullRange; m_expectedZero = expectedZero; - wpi::SendableRegistry::AddLW(this, "DutyCycle Encoder", - m_dutyCycle->GetSourceChannel()); + wpi::SendableRegistry::Add(this, "DutyCycle Encoder", + m_dutyCycle->GetSourceChannel()); } double DutyCycleEncoder::Get() const { diff --git a/wpilibc/src/main/native/cpp/Encoder.cpp b/wpilibc/src/main/native/cpp/Encoder.cpp index b7eda548fea..522f4801faf 100644 --- a/wpilibc/src/main/native/cpp/Encoder.cpp +++ b/wpilibc/src/main/native/cpp/Encoder.cpp @@ -234,7 +234,7 @@ void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType) { HAL_Report(HALUsageReporting::kResourceType_Encoder, GetFPGAIndex() + 1, encodingType); - wpi::SendableRegistry::AddLW(this, "Encoder", m_aSource->GetChannel()); + wpi::SendableRegistry::Add(this, "Encoder", m_aSource->GetChannel()); } double Encoder::DecodingScaleFactor() const { diff --git a/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp b/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp index 2a97988b19a..fc105a21193 100644 --- a/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp +++ b/wpilibc/src/main/native/cpp/IterativeRobotBase.cpp @@ -13,7 +13,6 @@ #include "frc/DSControlWord.h" #include "frc/Errors.h" -#include "frc/livewindow/LiveWindow.h" #include "frc/smartdashboard/SmartDashboard.h" using namespace frc; @@ -96,24 +95,6 @@ void IterativeRobotBase::SetNetworkTablesFlushEnabled(bool enabled) { m_ntFlushEnabled = enabled; } -void IterativeRobotBase::EnableLiveWindowInTest(bool testLW) { - static bool hasReported; - if (IsTestEnabled()) { - throw FRC_MakeError(err::IncompatibleMode, - "Can't configure test mode while in test mode!"); - } - if (!hasReported && testLW) { - HAL_Report(HALUsageReporting::kResourceType_SmartDashboard, - HALUsageReporting::kSmartDashboard_LiveWindow); - hasReported = true; - } - m_lwEnabledInTest = testLW; -} - -bool IterativeRobotBase::IsLiveWindowEnabledInTest() { - return m_lwEnabledInTest; -} - units::second_t IterativeRobotBase::GetPeriod() const { return m_period; } @@ -150,9 +131,6 @@ void IterativeRobotBase::LoopFunc() { } else if (m_lastMode == Mode::kTeleop) { TeleopExit(); } else if (m_lastMode == Mode::kTest) { - if (m_lwEnabledInTest) { - LiveWindow::SetEnabled(false); - } TestExit(); } @@ -167,9 +145,6 @@ void IterativeRobotBase::LoopFunc() { TeleopInit(); m_watchdog.AddEpoch("TeleopInit()"); } else if (mode == Mode::kTest) { - if (m_lwEnabledInTest) { - LiveWindow::SetEnabled(true); - } TestInit(); m_watchdog.AddEpoch("TestInit()"); } @@ -201,8 +176,6 @@ void IterativeRobotBase::LoopFunc() { SmartDashboard::UpdateValues(); m_watchdog.AddEpoch("SmartDashboard::UpdateValues()"); - LiveWindow::UpdateValues(); - m_watchdog.AddEpoch("LiveWindow::UpdateValues()"); if constexpr (IsSimulation()) { HAL_SimPeriodicBefore(); diff --git a/wpilibc/src/main/native/cpp/PWM.cpp b/wpilibc/src/main/native/cpp/PWM.cpp index f623ba40ff9..bf8d1b87cfc 100644 --- a/wpilibc/src/main/native/cpp/PWM.cpp +++ b/wpilibc/src/main/native/cpp/PWM.cpp @@ -40,7 +40,7 @@ PWM::PWM(int channel, bool registerSendable) { HAL_Report(HALUsageReporting::kResourceType_PWM, channel + 1); if (registerSendable) { - wpi::SendableRegistry::AddLW(this, "PWM", channel); + wpi::SendableRegistry::Add(this, "PWM", channel); } } @@ -174,7 +174,6 @@ int PWM::GetChannel() const { void PWM::InitSendable(wpi::SendableBuilder& builder) { builder.SetSmartDashboardType("PWM"); builder.SetActuator(true); - builder.SetSafeState([=, this] { SetDisabled(); }); builder.AddDoubleProperty( "Value", [=, this] { return GetPulseTime().value(); }, [=, this](double value) { SetPulseTime(units::millisecond_t{value}); }); diff --git a/wpilibc/src/main/native/cpp/PowerDistribution.cpp b/wpilibc/src/main/native/cpp/PowerDistribution.cpp index af0d308e656..a034723cbba 100644 --- a/wpilibc/src/main/native/cpp/PowerDistribution.cpp +++ b/wpilibc/src/main/native/cpp/PowerDistribution.cpp @@ -47,7 +47,7 @@ PowerDistribution::PowerDistribution() { HAL_Report(HALUsageReporting::kResourceType_PDP, HALUsageReporting::kPDP_REV); } - wpi::SendableRegistry::AddLW(this, "PowerDistribution", m_module); + wpi::SendableRegistry::Add(this, "PowerDistribution", m_module); } PowerDistribution::PowerDistribution(int module, ModuleType moduleType) { @@ -68,7 +68,7 @@ PowerDistribution::PowerDistribution(int module, ModuleType moduleType) { HAL_Report(HALUsageReporting::kResourceType_PDP, HALUsageReporting::kPDP_REV); } - wpi::SendableRegistry::AddLW(this, "PowerDistribution", m_module); + wpi::SendableRegistry::Add(this, "PowerDistribution", m_module); } int PowerDistribution::GetNumChannels() const { diff --git a/wpilibc/src/main/native/cpp/SharpIR.cpp b/wpilibc/src/main/native/cpp/SharpIR.cpp index 67e00f6a67e..084ad3b3cf5 100644 --- a/wpilibc/src/main/native/cpp/SharpIR.cpp +++ b/wpilibc/src/main/native/cpp/SharpIR.cpp @@ -31,7 +31,7 @@ SharpIR SharpIR::GP2Y0A51SK0F(int channel) { SharpIR::SharpIR(int channel, double a, double b, double minCM, double maxCM) : m_sensor(channel), m_A(a), m_B(b), m_minCM(minCM), m_maxCM(maxCM) { - wpi::SendableRegistry::AddLW(this, "SharpIR", channel); + wpi::SendableRegistry::Add(this, "SharpIR", channel); m_simDevice = hal::SimDevice("SharpIR", m_sensor.GetChannel()); if (m_simDevice) { diff --git a/wpilibc/src/main/native/cpp/Solenoid.cpp b/wpilibc/src/main/native/cpp/Solenoid.cpp index 819f79a8d71..5bccc8a762b 100644 --- a/wpilibc/src/main/native/cpp/Solenoid.cpp +++ b/wpilibc/src/main/native/cpp/Solenoid.cpp @@ -30,8 +30,8 @@ Solenoid::Solenoid(int module, PneumaticsModuleType moduleType, int channel) HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_channel + 1, m_module->GetModuleNumber() + 1); - wpi::SendableRegistry::AddLW(this, "Solenoid", m_module->GetModuleNumber(), - m_channel); + wpi::SendableRegistry::Add(this, "Solenoid", m_module->GetModuleNumber(), + m_channel); } Solenoid::Solenoid(PneumaticsModuleType moduleType, int channel) @@ -77,7 +77,6 @@ void Solenoid::StartPulse() { void Solenoid::InitSendable(wpi::SendableBuilder& builder) { builder.SetSmartDashboardType("Solenoid"); builder.SetActuator(true); - builder.SetSafeState([=, this] { Set(false); }); builder.AddBooleanProperty( "Value", [=, this] { return Get(); }, [=, this](bool value) { Set(value); }); diff --git a/wpilibc/src/main/native/cpp/Ultrasonic.cpp b/wpilibc/src/main/native/cpp/Ultrasonic.cpp index 640a56c4f41..3b50b913401 100644 --- a/wpilibc/src/main/native/cpp/Ultrasonic.cpp +++ b/wpilibc/src/main/native/cpp/Ultrasonic.cpp @@ -183,7 +183,7 @@ void Ultrasonic::Initialize() { static int instances = 0; instances++; HAL_Report(HALUsageReporting::kResourceType_Ultrasonic, instances); - wpi::SendableRegistry::AddLW(this, "Ultrasonic", m_echoChannel->GetChannel()); + wpi::SendableRegistry::Add(this, "Ultrasonic", m_echoChannel->GetChannel()); } void Ultrasonic::UltrasonicChecker() { diff --git a/wpilibc/src/main/native/cpp/counter/ExternalDirectionCounter.cpp b/wpilibc/src/main/native/cpp/counter/ExternalDirectionCounter.cpp index d518a2f0fc5..3b7d8a8aa4d 100644 --- a/wpilibc/src/main/native/cpp/counter/ExternalDirectionCounter.cpp +++ b/wpilibc/src/main/native/cpp/counter/ExternalDirectionCounter.cpp @@ -60,7 +60,7 @@ ExternalDirectionCounter::ExternalDirectionCounter( Reset(); HAL_Report(HALUsageReporting::kResourceType_Counter, m_index + 1); - wpi::SendableRegistry::AddLW(this, "External Direction Counter", m_index); + wpi::SendableRegistry::Add(this, "External Direction Counter", m_index); } int ExternalDirectionCounter::GetCount() const { diff --git a/wpilibc/src/main/native/cpp/counter/Tachometer.cpp b/wpilibc/src/main/native/cpp/counter/Tachometer.cpp index b5a32b807ed..aae658e8c46 100644 --- a/wpilibc/src/main/native/cpp/counter/Tachometer.cpp +++ b/wpilibc/src/main/native/cpp/counter/Tachometer.cpp @@ -34,7 +34,7 @@ Tachometer::Tachometer(std::shared_ptr source) { FRC_CheckErrorStatus(status, "{}", m_index); HAL_Report(HALUsageReporting::kResourceType_Counter, m_index + 1); - wpi::SendableRegistry::AddLW(this, "Tachometer", m_index); + wpi::SendableRegistry::Add(this, "Tachometer", m_index); } units::hertz_t Tachometer::GetFrequency() const { diff --git a/wpilibc/src/main/native/cpp/counter/UpDownCounter.cpp b/wpilibc/src/main/native/cpp/counter/UpDownCounter.cpp index 7da57924777..2cda45a0da8 100644 --- a/wpilibc/src/main/native/cpp/counter/UpDownCounter.cpp +++ b/wpilibc/src/main/native/cpp/counter/UpDownCounter.cpp @@ -54,7 +54,7 @@ UpDownCounter::UpDownCounter(std::shared_ptr upSource, Reset(); HAL_Report(HALUsageReporting::kResourceType_Counter, m_index + 1); - wpi::SendableRegistry::AddLW(this, "UpDown Counter", m_index); + wpi::SendableRegistry::Add(this, "UpDown Counter", m_index); } int UpDownCounter::GetCount() const { diff --git a/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp b/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp index 85232193a41..abd2df149c0 100644 --- a/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp +++ b/wpilibc/src/main/native/cpp/drive/DifferentialDrive.cpp @@ -35,7 +35,7 @@ DifferentialDrive::DifferentialDrive(std::function leftMotor, : m_leftMotor{std::move(leftMotor)}, m_rightMotor{std::move(rightMotor)} { static int instances = 0; ++instances; - wpi::SendableRegistry::AddLW(this, "DifferentialDrive", instances); + wpi::SendableRegistry::Add(this, "DifferentialDrive", instances); } void DifferentialDrive::ArcadeDrive(double xSpeed, double zRotation, @@ -194,7 +194,6 @@ std::string DifferentialDrive::GetDescription() const { void DifferentialDrive::InitSendable(wpi::SendableBuilder& builder) { builder.SetSmartDashboardType("DifferentialDrive"); builder.SetActuator(true); - builder.SetSafeState([=, this] { StopMotor(); }); builder.AddDoubleProperty( "Left Motor Speed", [&] { return m_leftOutput; }, m_leftMotor); builder.AddDoubleProperty( diff --git a/wpilibc/src/main/native/cpp/drive/MecanumDrive.cpp b/wpilibc/src/main/native/cpp/drive/MecanumDrive.cpp index d40d02c6343..0cafcb57c88 100644 --- a/wpilibc/src/main/native/cpp/drive/MecanumDrive.cpp +++ b/wpilibc/src/main/native/cpp/drive/MecanumDrive.cpp @@ -46,7 +46,7 @@ MecanumDrive::MecanumDrive(std::function frontLeftMotor, m_rearRightMotor{std::move(rearRightMotor)} { static int instances = 0; ++instances; - wpi::SendableRegistry::AddLW(this, "MecanumDrive", instances); + wpi::SendableRegistry::Add(this, "MecanumDrive", instances); } void MecanumDrive::DriveCartesian(double xSpeed, double ySpeed, @@ -133,7 +133,6 @@ std::string MecanumDrive::GetDescription() const { void MecanumDrive::InitSendable(wpi::SendableBuilder& builder) { builder.SetSmartDashboardType("MecanumDrive"); builder.SetActuator(true); - builder.SetSafeState([=, this] { StopMotor(); }); builder.AddDoubleProperty( "Front Left Motor Speed", [&] { return m_frontLeftOutput; }, m_frontLeftMotor); diff --git a/wpilibc/src/main/native/cpp/livewindow/LiveWindow.cpp b/wpilibc/src/main/native/cpp/livewindow/LiveWindow.cpp deleted file mode 100644 index 04f66c723e5..00000000000 --- a/wpilibc/src/main/native/cpp/livewindow/LiveWindow.cpp +++ /dev/null @@ -1,230 +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. - -#include "frc/livewindow/LiveWindow.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "frc/smartdashboard/SendableBuilderImpl.h" - -using namespace frc; - -static constexpr std::string_view kSmartDashboardType = "LW Subsystem"; - -namespace { -struct Component { - bool firstTime = true; - bool telemetryEnabled = false; - nt::StringPublisher namePub; - nt::StringPublisher typePub; -}; - -struct Instance { - Instance() { - wpi::SendableRegistry::SetLiveWindowBuilderFactory( - [] { return std::make_unique(); }); - enabledPub.Set(false); - } - - wpi::mutex mutex; - - int dataHandle = wpi::SendableRegistry::GetDataHandle(); - - std::shared_ptr liveWindowTable = - nt::NetworkTableInstance::GetDefault().GetTable("LiveWindow"); - std::shared_ptr statusTable = - liveWindowTable->GetSubTable(".status"); - nt::BooleanPublisher enabledPub = - statusTable->GetBooleanTopic("LW Enabled").Publish(); - - bool startLiveWindow = false; - bool liveWindowEnabled = false; - bool telemetryEnabled = false; - - std::function enabled; - std::function disabled; - - std::shared_ptr GetOrAdd(wpi::Sendable* sendable); -}; -} // namespace - -static std::unique_ptr& GetInstanceHolder() { - static std::unique_ptr instance = std::make_unique(); - return instance; -} - -static Instance& GetInstance() { - return *GetInstanceHolder(); -} - -#ifndef __FRC_ROBORIO__ -namespace frc::impl { -void ResetLiveWindow() { - std::make_unique().swap(GetInstanceHolder()); -} -} // namespace frc::impl -#endif - -std::shared_ptr Instance::GetOrAdd(wpi::Sendable* sendable) { - auto data = std::static_pointer_cast( - wpi::SendableRegistry::GetData(sendable, dataHandle)); - if (!data) { - data = std::make_shared(); - wpi::SendableRegistry::SetData(sendable, dataHandle, data); - } - return data; -} - -void LiveWindow::SetEnabledCallback(std::function func) { - ::GetInstance().enabled = func; -} - -void LiveWindow::SetDisabledCallback(std::function func) { - ::GetInstance().disabled = func; -} - -void LiveWindow::EnableTelemetry(wpi::Sendable* sendable) { - auto& inst = ::GetInstance(); - std::scoped_lock lock(inst.mutex); - // Re-enable global setting in case DisableAllTelemetry() was called. - inst.telemetryEnabled = true; - inst.GetOrAdd(sendable)->telemetryEnabled = true; -} - -void LiveWindow::DisableTelemetry(wpi::Sendable* sendable) { - auto& inst = ::GetInstance(); - std::scoped_lock lock(inst.mutex); - inst.GetOrAdd(sendable)->telemetryEnabled = false; -} - -void LiveWindow::DisableAllTelemetry() { - auto& inst = ::GetInstance(); - std::scoped_lock lock(inst.mutex); - inst.telemetryEnabled = false; - wpi::SendableRegistry::ForeachLiveWindow(inst.dataHandle, [&](auto& cbdata) { - if (!cbdata.data) { - cbdata.data = std::make_shared(); - } - std::static_pointer_cast(cbdata.data)->telemetryEnabled = false; - }); -} - -void LiveWindow::EnableAllTelemetry() { - auto& inst = ::GetInstance(); - std::scoped_lock lock(inst.mutex); - inst.telemetryEnabled = true; - wpi::SendableRegistry::ForeachLiveWindow(inst.dataHandle, [&](auto& cbdata) { - if (!cbdata.data) { - cbdata.data = std::make_shared(); - } - std::static_pointer_cast(cbdata.data)->telemetryEnabled = true; - }); -} - -bool LiveWindow::IsEnabled() { - auto& inst = ::GetInstance(); - std::scoped_lock lock(inst.mutex); - return inst.liveWindowEnabled; -} - -void LiveWindow::SetEnabled(bool enabled) { - auto& inst = ::GetInstance(); - std::scoped_lock lock(inst.mutex); - if (inst.liveWindowEnabled == enabled) { - return; - } - inst.startLiveWindow = enabled; - inst.liveWindowEnabled = enabled; - // Force table generation now to make sure everything is defined - UpdateValuesUnsafe(); - if (enabled) { - if (inst.enabled) { - inst.enabled(); - } - } else { - wpi::SendableRegistry::ForeachLiveWindow( - inst.dataHandle, [&](auto& cbdata) { - static_cast(cbdata.builder) - .StopLiveWindowMode(); - }); - if (inst.disabled) { - inst.disabled(); - } - } - inst.enabledPub.Set(enabled); -} - -void LiveWindow::UpdateValues() { - auto& inst = ::GetInstance(); - std::scoped_lock lock(inst.mutex); - UpdateValuesUnsafe(); -} - -void LiveWindow::UpdateValuesUnsafe() { - auto& inst = ::GetInstance(); - // Only do this if either LiveWindow mode or telemetry is enabled. - if (!inst.liveWindowEnabled && !inst.telemetryEnabled) { - return; - } - - wpi::SendableRegistry::ForeachLiveWindow(inst.dataHandle, [&](auto& cbdata) { - if (!cbdata.sendable || cbdata.parent) { - return; - } - - if (!cbdata.data) { - cbdata.data = std::make_shared(); - } - - auto& comp = *std::static_pointer_cast(cbdata.data); - - if (!inst.liveWindowEnabled && !comp.telemetryEnabled) { - return; - } - - if (comp.firstTime) { - // By holding off creating the NetworkTable entries, it allows the - // components to be redefined. This allows default sensor and actuator - // values to be created that are replaced with the custom names from - // users calling setName. - if (cbdata.name.empty()) { - return; - } - auto ssTable = inst.liveWindowTable->GetSubTable(cbdata.subsystem); - std::shared_ptr table; - // Treat name==subsystem as top level of subsystem - if (cbdata.name == cbdata.subsystem) { - table = ssTable; - } else { - table = ssTable->GetSubTable(cbdata.name); - } - comp.namePub = nt::StringTopic{table->GetTopic(".name")}.Publish(); - comp.namePub.Set(cbdata.name); - static_cast(cbdata.builder).SetTable(table); - cbdata.sendable->InitSendable(cbdata.builder); - comp.typePub = nt::StringTopic{ssTable->GetTopic(".type")}.PublishEx( - nt::StringTopic::kTypeString, - {{"SmartDashboard", kSmartDashboardType}}); - comp.typePub.Set(kSmartDashboardType); - - comp.firstTime = false; - } - - if (inst.startLiveWindow) { - static_cast(cbdata.builder).StartLiveWindowMode(); - } - cbdata.builder.Update(); - }); - - inst.startLiveWindow = false; -} diff --git a/wpilibc/src/main/native/cpp/motorcontrol/MotorControllerGroup.cpp b/wpilibc/src/main/native/cpp/motorcontrol/MotorControllerGroup.cpp index c5a0e0316f4..5c0266b054b 100644 --- a/wpilibc/src/main/native/cpp/motorcontrol/MotorControllerGroup.cpp +++ b/wpilibc/src/main/native/cpp/motorcontrol/MotorControllerGroup.cpp @@ -74,7 +74,6 @@ void MotorControllerGroup::StopMotor() { void MotorControllerGroup::InitSendable(wpi::SendableBuilder& builder) { builder.SetSmartDashboardType("Motor Controller"); builder.SetActuator(true); - builder.SetSafeState([=, this] { StopMotor(); }); builder.AddDoubleProperty( "Value", [=, this] { return Get(); }, [=, this](double value) { Set(value); }); diff --git a/wpilibc/src/main/native/cpp/motorcontrol/NidecBrushless.cpp b/wpilibc/src/main/native/cpp/motorcontrol/NidecBrushless.cpp index 5acf3c818d0..0342a01cea2 100644 --- a/wpilibc/src/main/native/cpp/motorcontrol/NidecBrushless.cpp +++ b/wpilibc/src/main/native/cpp/motorcontrol/NidecBrushless.cpp @@ -27,7 +27,7 @@ NidecBrushless::NidecBrushless(int pwmChannel, int dioChannel) m_dio.EnablePWM(0.5); HAL_Report(HALUsageReporting::kResourceType_NidecBrushless, pwmChannel + 1); - wpi::SendableRegistry::AddLW(this, "Nidec Brushless", pwmChannel); + wpi::SendableRegistry::Add(this, "Nidec Brushless", pwmChannel); } WPI_UNIGNORE_DEPRECATED @@ -79,7 +79,6 @@ int NidecBrushless::GetChannel() const { void NidecBrushless::InitSendable(wpi::SendableBuilder& builder) { builder.SetSmartDashboardType("Nidec Brushless"); builder.SetActuator(true); - builder.SetSafeState([=, this] { StopMotor(); }); builder.AddDoubleProperty( "Value", [=, this] { return Get(); }, [=, this](double value) { Set(value); }); diff --git a/wpilibc/src/main/native/cpp/motorcontrol/PWMMotorController.cpp b/wpilibc/src/main/native/cpp/motorcontrol/PWMMotorController.cpp index 28ef00fbef5..f33a54d79cf 100644 --- a/wpilibc/src/main/native/cpp/motorcontrol/PWMMotorController.cpp +++ b/wpilibc/src/main/native/cpp/motorcontrol/PWMMotorController.cpp @@ -94,7 +94,7 @@ WPI_IGNORE_DEPRECATED PWMMotorController::PWMMotorController(std::string_view name, int channel) : m_pwm(channel, false) { - wpi::SendableRegistry::AddLW(this, name, channel); + wpi::SendableRegistry::Add(this, name, channel); } WPI_UNIGNORE_DEPRECATED @@ -102,7 +102,6 @@ WPI_UNIGNORE_DEPRECATED void PWMMotorController::InitSendable(wpi::SendableBuilder& builder) { builder.SetSmartDashboardType("Motor Controller"); builder.SetActuator(true); - builder.SetSafeState([=, this] { Disable(); }); builder.AddDoubleProperty( "Value", [=, this] { return Get(); }, [=, this](double value) { Set(value); }); diff --git a/wpilibc/src/main/native/cpp/smartdashboard/SendableBuilderImpl.cpp b/wpilibc/src/main/native/cpp/smartdashboard/SendableBuilderImpl.cpp index 0098eae7367..ff42ea5cc85 100644 --- a/wpilibc/src/main/native/cpp/smartdashboard/SendableBuilderImpl.cpp +++ b/wpilibc/src/main/native/cpp/smartdashboard/SendableBuilderImpl.cpp @@ -77,20 +77,6 @@ void SendableBuilderImpl::StopListeners() { } } -void SendableBuilderImpl::StartLiveWindowMode() { - if (m_safeState) { - m_safeState(); - } - StartListeners(); -} - -void SendableBuilderImpl::StopLiveWindowMode() { - StopListeners(); - if (m_safeState) { - m_safeState(); - } -} - void SendableBuilderImpl::ClearProperties() { m_properties.clear(); } @@ -111,10 +97,6 @@ void SendableBuilderImpl::SetActuator(bool value) { m_actuator = value; } -void SendableBuilderImpl::SetSafeState(std::function func) { - m_safeState = func; -} - void SendableBuilderImpl::SetUpdateTable(wpi::unique_function func) { m_updateTables.emplace_back(std::move(func)); } diff --git a/wpilibc/src/main/native/cppcs/RobotBase.cpp b/wpilibc/src/main/native/cppcs/RobotBase.cpp index 58f1ec81b5c..c7113dc330a 100644 --- a/wpilibc/src/main/native/cppcs/RobotBase.cpp +++ b/wpilibc/src/main/native/cppcs/RobotBase.cpp @@ -26,7 +26,6 @@ #include "frc/DriverStation.h" #include "frc/Errors.h" #include "frc/Notifier.h" -#include "frc/livewindow/LiveWindow.h" #include "frc/smartdashboard/SmartDashboard.h" static_assert(frc::RuntimeType::kRoboRIO == @@ -333,7 +332,4 @@ RobotBase::RobotBase() { // Call DriverStation::RefreshData() to kick things off DriverStation::RefreshData(); - - // First and one-time initialization - LiveWindow::SetEnabled(false); } diff --git a/wpilibc/src/main/native/include/frc/IterativeRobotBase.h b/wpilibc/src/main/native/include/frc/IterativeRobotBase.h index 79f7fb2cab0..70cc2c34f48 100644 --- a/wpilibc/src/main/native/include/frc/IterativeRobotBase.h +++ b/wpilibc/src/main/native/include/frc/IterativeRobotBase.h @@ -212,19 +212,6 @@ class IterativeRobotBase : public RobotBase { [[deprecated("Deprecated without replacement.")]] void SetNetworkTablesFlushEnabled(bool enabled); - /** - * Sets whether LiveWindow operation is enabled during test mode. - * - * @param testLW True to enable, false to disable. Defaults to false. - * @throws if called in test mode. - */ - void EnableLiveWindowInTest(bool testLW); - - /** - * Whether LiveWindow operation is enabled during test mode. - */ - bool IsLiveWindowEnabledInTest(); - /** * Gets time period between calls to Periodic() functions. */ @@ -260,7 +247,6 @@ class IterativeRobotBase : public RobotBase { units::second_t m_period; Watchdog m_watchdog; bool m_ntFlushEnabled = true; - bool m_lwEnabledInTest = false; bool m_calledDsConnected = false; void PrintLoopOverrunMessage(); diff --git a/wpilibc/src/main/native/include/frc/PWM.h b/wpilibc/src/main/native/include/frc/PWM.h index cb9647dcc06..a7f174b9a3b 100644 --- a/wpilibc/src/main/native/include/frc/PWM.h +++ b/wpilibc/src/main/native/include/frc/PWM.h @@ -54,7 +54,6 @@ class PWM : public wpi::Sendable, public wpi::SendableHelper { * @param channel The PWM channel number. 0-9 are on-board, 10-19 are on the * MXP port * @param registerSendable If true, adds this instance to SendableRegistry - * and LiveWindow */ explicit PWM(int channel, bool registerSendable = true); diff --git a/wpilibc/src/main/native/include/frc/livewindow/LiveWindow.h b/wpilibc/src/main/native/include/frc/livewindow/LiveWindow.h deleted file mode 100644 index 2f0a34957ab..00000000000 --- a/wpilibc/src/main/native/include/frc/livewindow/LiveWindow.h +++ /dev/null @@ -1,90 +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 - -namespace wpi { -class Sendable; -} // namespace wpi - -namespace frc { - -/** - * The LiveWindow class is the public interface for putting sensors and - * actuators on the LiveWindow. - */ -class LiveWindow final { - public: - /** - * Sets function to be called when LiveWindow is enabled. - * - * @param func function (or nullptr for none) - */ - static void SetEnabledCallback(std::function func); - - /** - * Sets function to be called when LiveWindow is disabled. - * - * @param func function (or nullptr for none) - */ - static void SetDisabledCallback(std::function func); - - /** - * Enable telemetry for a single component. - * - * @param component sendable - */ - static void EnableTelemetry(wpi::Sendable* component); - - /** - * Disable telemetry for a single component. - * - * @param component sendable - */ - static void DisableTelemetry(wpi::Sendable* component); - - /** - * Disable ALL telemetry. - */ - static void DisableAllTelemetry(); - - /** - * Enable ALL telemetry. - */ - static void EnableAllTelemetry(); - - /** - * Returns true if LiveWindow is enabled. - * - * @return True if LiveWindow is enabled. - */ - static bool IsEnabled(); - - /** - * Change the enabled status of LiveWindow. - * - * If it changes to enabled, start livewindow running otherwise stop it - */ - static void SetEnabled(bool enabled); - - /** - * Tell all the sensors to update (send) their values. - * - * Actuators are handled through callbacks on their value changing from the - * SmartDashboard widgets. - */ - static void UpdateValues(); - - private: - LiveWindow() = default; - - /** - * Updates the entries, without using a mutex or lock. - */ - static void UpdateValuesUnsafe(); -}; - -} // namespace frc diff --git a/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilderImpl.h b/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilderImpl.h index 2051d1b5d59..026c77ba0c1 100644 --- a/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilderImpl.h +++ b/wpilibc/src/main/native/include/frc/smartdashboard/SendableBuilderImpl.h @@ -73,18 +73,6 @@ class SendableBuilderImpl : public nt::NTSendableBuilder { */ void StopListeners(); - /** - * Start LiveWindow mode by hooking the setters for all properties. Also - * calls the SafeState function if one was provided. - */ - void StartLiveWindowMode(); - - /** - * Stop LiveWindow mode by unhooking the setters for all properties. Also - * calls the SafeState function if one was provided. - */ - void StopLiveWindowMode(); - /** * Clear properties. */ @@ -92,7 +80,6 @@ class SendableBuilderImpl : public nt::NTSendableBuilder { void SetSmartDashboardType(std::string_view type) override; void SetActuator(bool value) override; - void SetSafeState(std::function func) override; void SetUpdateTable(wpi::unique_function func) override; nt::Topic GetTopic(std::string_view key) override; @@ -238,7 +225,6 @@ class SendableBuilderImpl : public nt::NTSendableBuilder { void AddSmallPropertyImpl(Topic topic, Getter getter, Setter setter); std::vector> m_properties; - std::function m_safeState; std::vector> m_updateTables; std::shared_ptr m_table; bool m_controllable = false; diff --git a/wpilibc/src/test/native/cpp/TimedRobotTest.cpp b/wpilibc/src/test/native/cpp/TimedRobotTest.cpp index d639ecce078..f25964a6f32 100644 --- a/wpilibc/src/test/native/cpp/TimedRobotTest.cpp +++ b/wpilibc/src/test/native/cpp/TimedRobotTest.cpp @@ -11,7 +11,6 @@ #include -#include "frc/livewindow/LiveWindow.h" #include "frc/simulation/DriverStationSim.h" #include "frc/simulation/SimHooks.h" @@ -20,7 +19,7 @@ using namespace frc; inline constexpr auto kPeriod = 20_ms; namespace { -class TimedRobotTest : public ::testing::TestWithParam { +class TimedRobotTest : public ::testing::Test { protected: void SetUp() override { frc::sim::PauseTiming(); } @@ -308,12 +307,8 @@ TEST_F(TimedRobotTest, TeleopMode) { robotThread.join(); } -TEST_P(TimedRobotTest, TestMode) { - bool isTestLW = GetParam(); - +TEST_F(TimedRobotTest, TestMode) { MockRobot robot; - robot.EnableLiveWindowInTest(isTestLW); - std::thread robotThread{[&] { robot.StartCompetition(); }}; frc::sim::DriverStationSim::SetEnabled(true); @@ -328,7 +323,6 @@ TEST_P(TimedRobotTest, TestMode) { EXPECT_EQ(0u, robot.m_autonomousInitCount); EXPECT_EQ(0u, robot.m_teleopInitCount); EXPECT_EQ(0u, robot.m_testInitCount); - EXPECT_FALSE(frc::LiveWindow::IsEnabled()); EXPECT_EQ(0u, robot.m_robotPeriodicCount); EXPECT_EQ(0u, robot.m_simulationPeriodicCount); @@ -350,9 +344,6 @@ TEST_P(TimedRobotTest, TestMode) { EXPECT_EQ(0u, robot.m_autonomousInitCount); EXPECT_EQ(0u, robot.m_teleopInitCount); EXPECT_EQ(1u, robot.m_testInitCount); - EXPECT_EQ(isTestLW, frc::LiveWindow::IsEnabled()); - - EXPECT_THROW(robot.EnableLiveWindowInTest(isTestLW), std::runtime_error); EXPECT_EQ(1u, robot.m_robotPeriodicCount); EXPECT_EQ(1u, robot.m_simulationPeriodicCount); @@ -399,7 +390,6 @@ TEST_P(TimedRobotTest, TestMode) { EXPECT_EQ(0u, robot.m_autonomousInitCount); EXPECT_EQ(0u, robot.m_teleopInitCount); EXPECT_EQ(1u, robot.m_testInitCount); - EXPECT_FALSE(frc::LiveWindow::IsEnabled()); EXPECT_EQ(3u, robot.m_robotPeriodicCount); EXPECT_EQ(3u, robot.m_simulationPeriodicCount); @@ -609,5 +599,3 @@ TEST_F(TimedRobotTest, AddPeriodicWithOffset) { robot.EndCompetition(); robotThread.join(); } - -INSTANTIATE_TEST_SUITE_P(TimedRobotTests, TimedRobotTest, testing::Bool()); diff --git a/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp index 50dbd4eeeb7..a10a421ba52 100644 --- a/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp +++ b/wpilibcExamples/src/main/cpp/templates/robotbaseskeleton/cpp/Robot.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -45,14 +44,12 @@ void Robot::StartCompetition() { wpi::WaitForObject(event.GetHandle()); } } else if (IsTest()) { - frc::LiveWindow::SetEnabled(true); modeThread.InTest(true); Test(); modeThread.InTest(false); while (IsTest() && IsEnabled()) { wpi::WaitForObject(event.GetHandle()); } - frc::LiveWindow::SetEnabled(false); } else { modeThread.InTeleop(true); Teleop(); diff --git a/wpilibcExamples/src/main/cpp/templates/timeslice/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/templates/timeslice/cpp/Robot.cpp index 7f79b234965..600204afb3b 100644 --- a/wpilibcExamples/src/main/cpp/templates/timeslice/cpp/Robot.cpp +++ b/wpilibcExamples/src/main/cpp/templates/timeslice/cpp/Robot.cpp @@ -4,16 +4,11 @@ #include "Robot.h" -#include #include #include // Run robot periodic() functions for 5 ms, and run controllers every 10 ms Robot::Robot() : frc::TimesliceRobot{5_ms, 10_ms} { - // LiveWindow causes drastic overruns in robot periodic functions that will - // interfere with controllers - frc::LiveWindow::DisableAllTelemetry(); - // Runs for 2 ms after robot periodic functions Schedule([=] {}, 2_ms); diff --git a/wpilibcExamples/src/main/cpp/templates/timesliceskeleton/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/templates/timesliceskeleton/cpp/Robot.cpp index 1a4f064affb..a76217a0db4 100644 --- a/wpilibcExamples/src/main/cpp/templates/timesliceskeleton/cpp/Robot.cpp +++ b/wpilibcExamples/src/main/cpp/templates/timesliceskeleton/cpp/Robot.cpp @@ -4,14 +4,8 @@ #include "Robot.h" -#include - // Run robot periodic() functions for 5 ms, and run controllers every 10 ms Robot::Robot() : frc::TimesliceRobot{5_ms, 10_ms} { - // LiveWindow causes drastic overruns in robot periodic functions that will - // interfere with controllers - frc::LiveWindow::DisableAllTelemetry(); - // Runs for 2 ms after robot periodic functions Schedule([=] {}, 2_ms); diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL345_I2C.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL345_I2C.java index 19ce55555e0..b898b3ea8ec 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL345_I2C.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/ADXL345_I2C.java @@ -135,7 +135,7 @@ public ADXL345_I2C(I2C.Port port, Range range, int deviceAddress) { setRange(range); HAL.report(tResourceType.kResourceType_ADXL345, tInstances.kADXL345_I2C); - SendableRegistry.addLW(this, "ADXL345_I2C", port.value); + SendableRegistry.add(this, "ADXL345_I2C", port.value); } /** diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogAccelerometer.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogAccelerometer.java index 0bdb2ffa2f6..27a1213998d 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogAccelerometer.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogAccelerometer.java @@ -26,7 +26,7 @@ public class AnalogAccelerometer implements Sendable, AutoCloseable { /** Common initialization. */ private void initAccelerometer() { HAL.report(tResourceType.kResourceType_Accelerometer, m_analogChannel.getChannel() + 1); - SendableRegistry.addLW(this, "Accelerometer", m_analogChannel.getChannel()); + SendableRegistry.add(this, "Accelerometer", m_analogChannel.getChannel()); } /** diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogEncoder.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogEncoder.java index 9d50a208a92..c455f4c2f67 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogEncoder.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogEncoder.java @@ -83,7 +83,7 @@ private void init(double fullRange, double expectedZero) { m_fullRange = fullRange; m_expectedZero = expectedZero; - SendableRegistry.addLW(this, "Analog Encoder", m_analogInput.getChannel()); + SendableRegistry.add(this, "Analog Encoder", m_analogInput.getChannel()); } private double mapSensorRange(double pos) { diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogGyro.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogGyro.java index 1628bf78785..2bca5771896 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogGyro.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogGyro.java @@ -29,7 +29,7 @@ public class AnalogGyro implements Sendable, AutoCloseable { /** Initialize the gyro. Calibration is handled by calibrate(). */ private void initGyro() { HAL.report(tResourceType.kResourceType_Gyro, m_analog.getChannel() + 1); - SendableRegistry.addLW(this, "AnalogGyro", m_analog.getChannel()); + SendableRegistry.add(this, "AnalogGyro", m_analog.getChannel()); } /** diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogInput.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogInput.java index e3a786bc951..e17721f9179 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogInput.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogInput.java @@ -42,7 +42,7 @@ public AnalogInput(final int channel) { m_port = AnalogJNI.initializeAnalogInputPort(portHandle); HAL.report(tResourceType.kResourceType_AnalogChannel, channel + 1); - SendableRegistry.addLW(this, "AnalogInput", channel); + SendableRegistry.add(this, "AnalogInput", channel); } @Override diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogPotentiometer.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogPotentiometer.java index 15473495528..b7c32b23909 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogPotentiometer.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogPotentiometer.java @@ -56,7 +56,7 @@ public AnalogPotentiometer(final int channel, double fullRange, double offset) { */ @SuppressWarnings("this-escape") public AnalogPotentiometer(final AnalogInput input, double fullRange, double offset) { - SendableRegistry.addLW(this, "AnalogPotentiometer", input.getChannel()); + SendableRegistry.add(this, "AnalogPotentiometer", input.getChannel()); m_analogInput = input; m_initAnalogInput = false; diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogTrigger.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogTrigger.java index 10949a88236..a205e503368 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogTrigger.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AnalogTrigger.java @@ -52,7 +52,7 @@ public AnalogTrigger(AnalogInput channel) { int index = getIndex(); HAL.report(tResourceType.kResourceType_AnalogTrigger, index + 1); - SendableRegistry.addLW(this, "AnalogTrigger", index); + SendableRegistry.add(this, "AnalogTrigger", index); } /** @@ -69,7 +69,7 @@ public AnalogTrigger(DutyCycle input) { int index = getIndex(); HAL.report(tResourceType.kResourceType_AnalogTrigger, index + 1); - SendableRegistry.addLW(this, "AnalogTrigger", index); + SendableRegistry.add(this, "AnalogTrigger", index); } @Override diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Compressor.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Compressor.java index 38dee091285..b43a3949e67 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Compressor.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Compressor.java @@ -45,7 +45,7 @@ public Compressor(int module, PneumaticsModuleType moduleType) { m_module.enableCompressorDigital(); HAL.report(tResourceType.kResourceType_Compressor, module + 1); - SendableRegistry.addLW(this, "Compressor", module); + SendableRegistry.add(this, "Compressor", module); } /** diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Counter.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Counter.java index c4bc1738777..f984aa0b67f 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Counter.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Counter.java @@ -85,7 +85,7 @@ public Counter(final Mode mode) { setMaxPeriod(0.5); HAL.report(tResourceType.kResourceType_Counter, m_index + 1, mode.value + 1); - SendableRegistry.addLW(this, "Counter", m_index); + SendableRegistry.add(this, "Counter", m_index); } /** diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalInput.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalInput.java index ab3d5e5e4c7..edd91cdebdb 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalInput.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalInput.java @@ -35,7 +35,7 @@ public DigitalInput(int channel) { m_handle = DIOJNI.initializeDIOPort(HAL.getPort((byte) channel), true); HAL.report(tResourceType.kResourceType_DigitalInput, channel + 1); - SendableRegistry.addLW(this, "DigitalInput", channel); + SendableRegistry.add(this, "DigitalInput", channel); } @Override diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalOutput.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalOutput.java index a7446f6068b..87ed908c94b 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalOutput.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DigitalOutput.java @@ -37,7 +37,7 @@ public DigitalOutput(int channel) { m_handle = DIOJNI.initializeDIOPort(HAL.getPort((byte) channel), false); HAL.report(tResourceType.kResourceType_DigitalOutput, channel + 1); - SendableRegistry.addLW(this, "DigitalOutput", channel); + SendableRegistry.add(this, "DigitalOutput", channel); } @Override diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DoubleSolenoid.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DoubleSolenoid.java index aab8b1e1060..73eae77a2f9 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DoubleSolenoid.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DoubleSolenoid.java @@ -99,7 +99,7 @@ public DoubleSolenoid( tResourceType.kResourceType_Solenoid, forwardChannel + 1, m_module.getModuleNumber() + 1); HAL.report( tResourceType.kResourceType_Solenoid, reverseChannel + 1, m_module.getModuleNumber() + 1); - SendableRegistry.addLW(this, "DoubleSolenoid", m_module.getModuleNumber(), forwardChannel); + SendableRegistry.add(this, "DoubleSolenoid", m_module.getModuleNumber(), forwardChannel); successfulCompletion = true; } finally { if (!successfulCompletion) { @@ -210,7 +210,6 @@ public boolean isRevSolenoidDisabled() { public void initSendable(SendableBuilder builder) { builder.setSmartDashboardType("Double Solenoid"); builder.setActuator(true); - builder.setSafeState(() -> set(Value.kOff)); builder.addStringProperty( "Value", () -> get().name().substring(1), diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycle.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycle.java index 342b87ef798..22ded084ac0 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycle.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycle.java @@ -36,7 +36,7 @@ public DutyCycle(int channel) { m_channel = channel; HAL.report(tResourceType.kResourceType_DutyCycle, channel + 1); - SendableRegistry.addLW(this, "Duty Cycle", channel); + SendableRegistry.add(this, "Duty Cycle", channel); } /** Close the DutyCycle and free all resources. */ diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycleEncoder.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycleEncoder.java index 4b4b44d5818..e5e58fe8c90 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycleEncoder.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/DutyCycleEncoder.java @@ -93,7 +93,7 @@ private void init(double fullRange, double expectedZero) { m_fullRange = fullRange; m_expectedZero = expectedZero; - SendableRegistry.addLW(this, "DutyCycle Encoder", m_dutyCycle.getSourceChannel()); + SendableRegistry.add(this, "DutyCycle Encoder", m_dutyCycle.getSourceChannel()); } private double mapSensorRange(double pos) { diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Encoder.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Encoder.java index 76b0b4bb10d..c851de15d07 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Encoder.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Encoder.java @@ -84,7 +84,7 @@ private void initEncoder(boolean reverseDirection, final EncodingType type) { int fpgaIndex = getFPGAIndex(); HAL.report(tResourceType.kResourceType_Encoder, fpgaIndex + 1, type.value + 1); - SendableRegistry.addLW(this, "Encoder", fpgaIndex); + SendableRegistry.add(this, "Encoder", fpgaIndex); } /** diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/IterativeRobotBase.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/IterativeRobotBase.java index ed4d9de959f..2d136585f52 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/IterativeRobotBase.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/IterativeRobotBase.java @@ -5,13 +5,9 @@ package edu.wpi.first.wpilibj; import edu.wpi.first.hal.DriverStationJNI; -import edu.wpi.first.hal.FRCNetComm.tInstances; -import edu.wpi.first.hal.FRCNetComm.tResourceType; import edu.wpi.first.hal.HAL; import edu.wpi.first.networktables.NetworkTableInstance; -import edu.wpi.first.wpilibj.livewindow.LiveWindow; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; -import java.util.ConcurrentModificationException; /** * IterativeRobotBase implements a specific type of robot program framework, extending the RobotBase @@ -71,7 +67,6 @@ private enum Mode { private final double m_period; private final Watchdog m_watchdog; private boolean m_ntFlushEnabled = true; - private boolean m_lwEnabledInTest; private boolean m_calledDsConnected; /** @@ -259,34 +254,6 @@ public void setNetworkTablesFlushEnabled(boolean enabled) { m_ntFlushEnabled = enabled; } - private boolean m_reportedLw; - - /** - * Sets whether LiveWindow operation is enabled during test mode. Calling - * - * @param testLW True to enable, false to disable. Defaults to false. - * @throws ConcurrentModificationException if this is called during test mode. - */ - public void enableLiveWindowInTest(boolean testLW) { - if (isTestEnabled()) { - throw new ConcurrentModificationException("Can't configure test mode while in test mode!"); - } - if (!m_reportedLw && testLW) { - HAL.report(tResourceType.kResourceType_SmartDashboard, tInstances.kSmartDashboard_LiveWindow); - m_reportedLw = true; - } - m_lwEnabledInTest = testLW; - } - - /** - * Whether LiveWindow operation is enabled during test mode. - * - * @return whether LiveWindow should be enabled in test mode. - */ - public boolean isLiveWindowEnabledInTest() { - return m_lwEnabledInTest; - } - /** * Gets time period between calls to Periodic() functions. * @@ -327,12 +294,7 @@ protected void loopFunc() { case kDisabled -> disabledExit(); case kAutonomous -> autonomousExit(); case kTeleop -> teleopExit(); - case kTest -> { - if (m_lwEnabledInTest) { - LiveWindow.setEnabled(false); - } - testExit(); - } + case kTest -> testExit(); default -> { // NOP } @@ -353,9 +315,6 @@ protected void loopFunc() { m_watchdog.addEpoch("teleopInit()"); } case kTest -> { - if (m_lwEnabledInTest) { - LiveWindow.setEnabled(true); - } testInit(); m_watchdog.addEpoch("testInit()"); } @@ -399,8 +358,6 @@ protected void loopFunc() { SmartDashboard.updateValues(); m_watchdog.addEpoch("SmartDashboard.updateValues()"); - LiveWindow.updateValues(); - m_watchdog.addEpoch("LiveWindow.updateValues()"); if (isSimulation()) { HAL.simPeriodicBefore(); diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PWM.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PWM.java index fa4218a0235..460424abfba 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PWM.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PWM.java @@ -40,7 +40,7 @@ public enum PeriodMultiplier { *

Checks channel value range and allocates the appropriate channel. The allocation is only * done to help users ensure that they don't double assign channels. * - *

By default, adds itself to SendableRegistry and LiveWindow. + *

By default, adds itself to SendableRegistry. * * @param channel The PWM channel number. 0-9 are on-board, 10-19 are on the MXP port */ @@ -52,7 +52,7 @@ public PWM(final int channel) { * Allocate a PWM given a channel. * * @param channel The PWM channel number. 0-9 are on-board, 10-19 are on the MXP port - * @param registerSendable If true, adds this instance to SendableRegistry and LiveWindow + * @param registerSendable If true, adds this instance to SendableRegistry */ @SuppressWarnings("this-escape") public PWM(final int channel, final boolean registerSendable) { @@ -67,7 +67,7 @@ public PWM(final int channel, final boolean registerSendable) { HAL.report(tResourceType.kResourceType_PWM, channel + 1); if (registerSendable) { - SendableRegistry.addLW(this, "PWM", channel); + SendableRegistry.add(this, "PWM", channel); } } @@ -244,7 +244,6 @@ public int getHandle() { public void initSendable(SendableBuilder builder) { builder.setSmartDashboardType("PWM"); builder.setActuator(true); - builder.setSafeState(this::setDisabled); builder.addDoubleProperty( "Value", this::getPulseTimeMicroseconds, value -> setPulseTimeMicroseconds((int) value)); builder.addDoubleProperty("Speed", this::getSpeed, this::setSpeed); diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PowerDistribution.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PowerDistribution.java index 15f8e0ec246..e26c8a2d865 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/PowerDistribution.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/PowerDistribution.java @@ -57,7 +57,7 @@ public PowerDistribution(int module, ModuleType moduleType) { } else { HAL.report(tResourceType.kResourceType_PDP, tInstances.kPDP_REV); } - SendableRegistry.addLW(this, "PowerDistribution", m_module); + SendableRegistry.add(this, "PowerDistribution", m_module); } /** @@ -76,7 +76,7 @@ public PowerDistribution() { HAL.report(tResourceType.kResourceType_PDP, tInstances.kPDP_REV); } - SendableRegistry.addLW(this, "PowerDistribution", m_module); + SendableRegistry.add(this, "PowerDistribution", m_module); } @Override diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java index 775562e293c..193c5f74492 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java @@ -17,7 +17,6 @@ import edu.wpi.first.networktables.NetworkTableEvent; import edu.wpi.first.networktables.NetworkTableInstance; import edu.wpi.first.util.WPIUtilJNI; -import edu.wpi.first.wpilibj.livewindow.LiveWindow; import edu.wpi.first.wpilibj.util.WPILibVersion; import java.io.File; import java.io.IOException; @@ -224,8 +223,6 @@ protected RobotBase() { } } }); - - LiveWindow.setEnabled(false); } /** diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/SharpIR.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/SharpIR.java index 66993da1b2f..98317a099c6 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/SharpIR.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/SharpIR.java @@ -89,7 +89,7 @@ public SharpIR(int channel, double a, double b, double minCM, double maxCM) { m_minCM = minCM; m_maxCM = maxCM; - SendableRegistry.addLW(this, "SharpIR", channel); + SendableRegistry.add(this, "SharpIR", channel); m_simDevice = SimDevice.create("SharpIR", m_sensor.getChannel()); if (m_simDevice != null) { diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Solenoid.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Solenoid.java index 9c516da72f2..6f78a6130a7 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Solenoid.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Solenoid.java @@ -57,7 +57,7 @@ public Solenoid(final int module, final PneumaticsModuleType moduleType, final i } HAL.report(tResourceType.kResourceType_Solenoid, channel + 1, m_module.getModuleNumber() + 1); - SendableRegistry.addLW(this, "Solenoid", m_module.getModuleNumber(), channel); + SendableRegistry.add(this, "Solenoid", m_module.getModuleNumber(), channel); } @Override @@ -148,7 +148,6 @@ public void startPulse() { public void initSendable(SendableBuilder builder) { builder.setSmartDashboardType("Solenoid"); builder.setActuator(true); - builder.setSafeState(() -> set(false)); builder.addBooleanProperty("Value", this::get, this::set); } } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Ultrasonic.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Ultrasonic.java index 14103544ce3..bfd5903662c 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/Ultrasonic.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/Ultrasonic.java @@ -107,7 +107,7 @@ private synchronized void initialize() { m_instances++; HAL.report(tResourceType.kResourceType_Ultrasonic, m_instances); - SendableRegistry.addLW(this, "Ultrasonic", m_echoChannel.getChannel()); + SendableRegistry.add(this, "Ultrasonic", m_echoChannel.getChannel()); } /** diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/ExternalDirectionCounter.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/ExternalDirectionCounter.java index 97fbf5b464d..fb78ff5f821 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/ExternalDirectionCounter.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/ExternalDirectionCounter.java @@ -60,7 +60,7 @@ public ExternalDirectionCounter(DigitalSource countSource, DigitalSource directi int intIndex = index.getInt(); HAL.report(tResourceType.kResourceType_Counter, intIndex + 1); - SendableRegistry.addLW(this, "External Direction Counter", intIndex); + SendableRegistry.add(this, "External Direction Counter", intIndex); } /** diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/Tachometer.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/Tachometer.java index 6bef24deaa7..cba2c92444a 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/Tachometer.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/Tachometer.java @@ -49,7 +49,7 @@ public Tachometer(DigitalSource source) { int intIndex = index.getInt(); HAL.report(tResourceType.kResourceType_Counter, intIndex + 1); - SendableRegistry.addLW(this, "Tachometer", intIndex); + SendableRegistry.add(this, "Tachometer", intIndex); } @Override diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/UpDownCounter.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/UpDownCounter.java index ed9f35e971f..603a5cd921d 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/UpDownCounter.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/counter/UpDownCounter.java @@ -63,7 +63,7 @@ public UpDownCounter(DigitalSource upSource, DigitalSource downSource) { int intIndex = index.getInt(); HAL.report(tResourceType.kResourceType_Counter, intIndex + 1); - SendableRegistry.addLW(this, "UpDown Counter", intIndex); + SendableRegistry.add(this, "UpDown Counter", intIndex); } @Override diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/drive/DifferentialDrive.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/drive/DifferentialDrive.java index 40e34a803da..dba563305f9 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/drive/DifferentialDrive.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/drive/DifferentialDrive.java @@ -127,7 +127,7 @@ public DifferentialDrive(DoubleConsumer leftMotor, DoubleConsumer rightMotor) { m_leftMotor = leftMotor; m_rightMotor = rightMotor; instances++; - SendableRegistry.addLW(this, "DifferentialDrive", instances); + SendableRegistry.add(this, "DifferentialDrive", instances); } @Override @@ -367,7 +367,6 @@ public String getDescription() { public void initSendable(SendableBuilder builder) { builder.setSmartDashboardType("DifferentialDrive"); builder.setActuator(true); - builder.setSafeState(this::stopMotor); builder.addDoubleProperty("Left Motor Speed", () -> m_leftOutput, m_leftMotor); builder.addDoubleProperty("Right Motor Speed", () -> m_rightOutput, m_rightMotor); } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/drive/MecanumDrive.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/drive/MecanumDrive.java index df043622722..9250aba6fae 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/drive/MecanumDrive.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/drive/MecanumDrive.java @@ -158,7 +158,7 @@ public MecanumDrive( m_frontRightMotor = frontRightMotor; m_rearRightMotor = rearRightMotor; instances++; - SendableRegistry.addLW(this, "MecanumDrive", instances); + SendableRegistry.add(this, "MecanumDrive", instances); } @Override @@ -317,7 +317,6 @@ public String getDescription() { public void initSendable(SendableBuilder builder) { builder.setSmartDashboardType("MecanumDrive"); builder.setActuator(true); - builder.setSafeState(this::stopMotor); builder.addDoubleProperty("Front Left Motor Speed", () -> m_frontLeftOutput, m_frontLeftMotor); builder.addDoubleProperty( "Front Right Motor Speed", () -> m_frontRightOutput, m_frontRightMotor); diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/livewindow/LiveWindow.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/livewindow/LiveWindow.java deleted file mode 100644 index f30ac59d178..00000000000 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/livewindow/LiveWindow.java +++ /dev/null @@ -1,247 +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. - -package edu.wpi.first.wpilibj.livewindow; - -import edu.wpi.first.networktables.BooleanPublisher; -import edu.wpi.first.networktables.NetworkTable; -import edu.wpi.first.networktables.NetworkTableInstance; -import edu.wpi.first.networktables.StringPublisher; -import edu.wpi.first.networktables.StringTopic; -import edu.wpi.first.util.sendable.Sendable; -import edu.wpi.first.util.sendable.SendableRegistry; -import edu.wpi.first.wpilibj.smartdashboard.SendableBuilderImpl; - -/** - * The LiveWindow class is the public interface for putting sensors and actuators on the LiveWindow. - */ -public final class LiveWindow { - private static final class Component implements AutoCloseable { - @Override - public void close() { - if (m_namePub != null) { - m_namePub.close(); - m_namePub = null; - } - if (m_typePub != null) { - m_typePub.close(); - m_typePub = null; - } - } - - boolean m_firstTime = true; - boolean m_telemetryEnabled; - StringPublisher m_namePub; - StringPublisher m_typePub; - } - - private static final String kSmartDashboardType = "LW Subsystem"; - - private static final int dataHandle = SendableRegistry.getDataHandle(); - private static final NetworkTable liveWindowTable = - NetworkTableInstance.getDefault().getTable("LiveWindow"); - private static final NetworkTable statusTable = liveWindowTable.getSubTable(".status"); - private static final BooleanPublisher enabledPub = - statusTable.getBooleanTopic("LW Enabled").publish(); - private static boolean startLiveWindow; - private static boolean liveWindowEnabled; - private static boolean telemetryEnabled; - - private static Runnable enabledListener; - private static Runnable disabledListener; - - static { - SendableRegistry.setLiveWindowBuilderFactory(SendableBuilderImpl::new); - enabledPub.set(false); - } - - private static Component getOrAdd(Sendable sendable) { - Component data = (Component) SendableRegistry.getData(sendable, dataHandle); - if (data == null) { - data = new Component(); - SendableRegistry.setData(sendable, dataHandle, data); - } - return data; - } - - private LiveWindow() { - throw new UnsupportedOperationException("This is a utility class!"); - } - - /** - * Sets function to be called when LiveWindow is enabled. - * - * @param runnable function (or null for none) - */ - public static synchronized void setEnabledListener(Runnable runnable) { - enabledListener = runnable; - } - - /** - * Sets function to be called when LiveWindow is disabled. - * - * @param runnable function (or null for none) - */ - public static synchronized void setDisabledListener(Runnable runnable) { - disabledListener = runnable; - } - - /** - * Returns true if LiveWindow is enabled. - * - * @return True if LiveWindow is enabled. - */ - public static synchronized boolean isEnabled() { - return liveWindowEnabled; - } - - /** - * Set the enabled state of LiveWindow. - * - *

If it's being enabled, turn off the scheduler and remove all the commands from the queue and - * enable all the components registered for LiveWindow. If it's being disabled, stop all the - * registered components and re-enable the scheduler. - * - *

TODO: add code to disable PID loops when enabling LiveWindow. The commands should re-enable - * the PID loops themselves when they get rescheduled. This prevents arms from starting to move - * around, etc. after a period of adjusting them in LiveWindow mode. - * - * @param enabled True to enable LiveWindow. - */ - public static synchronized void setEnabled(boolean enabled) { - if (liveWindowEnabled != enabled) { - startLiveWindow = enabled; - liveWindowEnabled = enabled; - updateValues(); // Force table generation now to make sure everything is defined - if (enabled) { - System.out.println("Starting live window mode."); - if (enabledListener != null) { - enabledListener.run(); - } - } else { - System.out.println("stopping live window mode."); - SendableRegistry.foreachLiveWindow( - dataHandle, cbdata -> ((SendableBuilderImpl) cbdata.builder).stopLiveWindowMode()); - if (disabledListener != null) { - disabledListener.run(); - } - } - enabledPub.set(enabled); - } - } - - /** - * Enable telemetry for a single component. - * - * @param sendable component - */ - public static synchronized void enableTelemetry(Sendable sendable) { - // Re-enable global setting in case disableAllTelemetry() was called. - telemetryEnabled = true; - getOrAdd(sendable).m_telemetryEnabled = true; - } - - /** - * Disable telemetry for a single component. - * - * @param sendable component - */ - public static synchronized void disableTelemetry(Sendable sendable) { - getOrAdd(sendable).m_telemetryEnabled = false; - } - - /** Disable ALL telemetry. */ - public static synchronized void disableAllTelemetry() { - telemetryEnabled = false; - SendableRegistry.foreachLiveWindow( - dataHandle, - cbdata -> { - if (cbdata.data == null) { - cbdata.data = new Component(); - } - ((Component) cbdata.data).m_telemetryEnabled = false; - }); - } - - /** Enable ALL telemetry. */ - public static synchronized void enableAllTelemetry() { - telemetryEnabled = true; - SendableRegistry.foreachLiveWindow( - dataHandle, - cbdata -> { - if (cbdata.data == null) { - cbdata.data = new Component(); - } - ((Component) cbdata.data).m_telemetryEnabled = true; - }); - } - - /** - * Tell all the sensors to update (send) their values. - * - *

Actuators are handled through callbacks on their value changing from the SmartDashboard - * widgets. - */ - public static synchronized void updateValues() { - // Only do this if either LiveWindow mode or telemetry is enabled. - if (!liveWindowEnabled && !telemetryEnabled) { - return; - } - - SendableRegistry.foreachLiveWindow( - dataHandle, - cbdata -> { - if (cbdata.sendable == null || cbdata.parent != null) { - return; - } - - if (cbdata.data == null) { - cbdata.data = new Component(); - } - - Component component = (Component) cbdata.data; - - if (!liveWindowEnabled && !component.m_telemetryEnabled) { - return; - } - - if (component.m_firstTime) { - // By holding off creating the NetworkTable entries, it allows the - // components to be redefined. This allows default sensor and actuator - // values to be created that are replaced with the custom names from - // users calling setName. - if (cbdata.name.isEmpty()) { - return; - } - NetworkTable ssTable = liveWindowTable.getSubTable(cbdata.subsystem); - NetworkTable table; - // Treat name==subsystem as top level of subsystem - if (cbdata.name.equals(cbdata.subsystem)) { - table = ssTable; - } else { - table = ssTable.getSubTable(cbdata.name); - } - component.m_namePub = new StringTopic(table.getTopic(".name")).publish(); - component.m_namePub.set(cbdata.name); - ((SendableBuilderImpl) cbdata.builder).setTable(table); - cbdata.sendable.initSendable(cbdata.builder); - component.m_typePub = - new StringTopic(ssTable.getTopic(".type")) - .publishEx( - StringTopic.kTypeString, - "{\"SmartDashboard\":\"" + kSmartDashboardType + "\"}"); - component.m_typePub.set(kSmartDashboardType); - - component.m_firstTime = false; - } - - if (startLiveWindow) { - ((SendableBuilderImpl) cbdata.builder).startLiveWindowMode(); - } - cbdata.builder.update(); - }); - - startLiveWindow = false; - } -} diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/MotorControllerGroup.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/MotorControllerGroup.java index c56496cd480..d0322ead838 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/MotorControllerGroup.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/MotorControllerGroup.java @@ -53,7 +53,7 @@ private void init() { SendableRegistry.addChild(this, controller); } instances++; - SendableRegistry.addLW(this, "MotorControllerGroup", instances); + SendableRegistry.add(this, "MotorControllerGroup", instances); } @Override @@ -111,7 +111,6 @@ public void stopMotor() { public void initSendable(SendableBuilder builder) { builder.setSmartDashboardType("Motor Controller"); builder.setActuator(true); - builder.setSafeState(this::stopMotor); builder.addDoubleProperty("Value", this::get, this::set); } } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/NidecBrushless.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/NidecBrushless.java index 01af76563cb..0f3d5ad95ec 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/NidecBrushless.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/NidecBrushless.java @@ -46,7 +46,7 @@ public NidecBrushless(final int pwmChannel, final int dioChannel) { SendableRegistry.addChild(this, m_pwm); HAL.report(tResourceType.kResourceType_NidecBrushless, pwmChannel + 1); - SendableRegistry.addLW(this, "Nidec Brushless", pwmChannel); + SendableRegistry.add(this, "Nidec Brushless", pwmChannel); } @Override @@ -139,7 +139,6 @@ public int getChannel() { public void initSendable(SendableBuilder builder) { builder.setSmartDashboardType("Nidec Brushless"); builder.setActuator(true); - builder.setSafeState(this::stopMotor); builder.addDoubleProperty("Value", this::get, this::set); } } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/PWMMotorController.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/PWMMotorController.java index 803f57d73b5..6ebd8f9c861 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/PWMMotorController.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/motorcontrol/PWMMotorController.java @@ -32,7 +32,7 @@ public abstract class PWMMotorController extends MotorSafety @SuppressWarnings("this-escape") protected PWMMotorController(final String name, final int channel) { m_pwm = new PWM(channel, false); - SendableRegistry.addLW(this, name, channel); + SendableRegistry.add(this, name, channel); } /** Free the resource associated with the PWM channel and set the value to 0. */ @@ -161,7 +161,6 @@ public void addFollower(PWMMotorController follower) { public void initSendable(SendableBuilder builder) { builder.setSmartDashboardType("Motor Controller"); builder.setActuator(true); - builder.setSafeState(this::disable); builder.addDoubleProperty("Value", this::get, this::set); } } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SendableBuilderImpl.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SendableBuilderImpl.java index 09a16860e53..f38293d88df 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SendableBuilderImpl.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/smartdashboard/SendableBuilderImpl.java @@ -98,7 +98,6 @@ void update(boolean controllable, long time) { } private final List> m_properties = new ArrayList<>(); - private Runnable m_safeState; private final List m_updateTables = new ArrayList<>(); private NetworkTable m_table; private boolean m_controllable; @@ -205,28 +204,6 @@ public void stopListeners() { } } - /** - * Start LiveWindow mode by hooking the setters for all properties. Also calls the safeState - * function if one was provided. - */ - public void startLiveWindowMode() { - if (m_safeState != null) { - m_safeState.run(); - } - startListeners(); - } - - /** - * Stop LiveWindow mode by unhooking the setters for all properties. Also calls the safeState - * function if one was provided. - */ - public void stopLiveWindowMode() { - stopListeners(); - if (m_safeState != null) { - m_safeState.run(); - } - } - /** Clear properties. */ @Override public void clearProperties() { @@ -274,17 +251,6 @@ public void setActuator(boolean value) { m_actuator = value; } - /** - * Set the function that should be called to set the Sendable into a safe state. This is called - * when entering and exiting Live Window mode. - * - * @param func function - */ - @Override - public void setSafeState(Runnable func) { - m_safeState = func; - } - /** * Set the function that should be called to update the network table for things other than * properties. Note this function is not passed the network table object; instead it should use diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/TimedRobotTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/TimedRobotTest.java index da0bd92bdb3..1d3f0e70e6e 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/TimedRobotTest.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/TimedRobotTest.java @@ -5,20 +5,14 @@ package edu.wpi.first.wpilibj; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import edu.wpi.first.wpilibj.livewindow.LiveWindow; import edu.wpi.first.wpilibj.simulation.DriverStationSim; import edu.wpi.first.wpilibj.simulation.SimHooks; -import java.util.ConcurrentModificationException; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.ResourceLock; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; class TimedRobotTest { static final double kPeriod = 0.02; @@ -389,12 +383,10 @@ void teleopModeTest() { robot.close(); } - @ValueSource(booleans = {true, false}) - @ParameterizedTest + @Test @ResourceLock("timing") - void testModeTest(boolean isLW) { + void testModeTest() { MockRobot robot = new MockRobot(); - robot.enableLiveWindowInTest(isLW); Thread robotThread = new Thread(robot::startCompetition); robotThread.start(); @@ -411,7 +403,6 @@ void testModeTest(boolean isLW) { assertEquals(0, robot.m_autonomousInitCount.get()); assertEquals(0, robot.m_teleopInitCount.get()); assertEquals(0, robot.m_testInitCount.get()); - assertFalse(LiveWindow.isEnabled()); assertEquals(0, robot.m_robotPeriodicCount.get()); assertEquals(0, robot.m_simulationPeriodicCount.get()); @@ -454,9 +445,6 @@ void testModeTest(boolean isLW) { assertEquals(0, robot.m_autonomousInitCount.get()); assertEquals(0, robot.m_teleopInitCount.get()); assertEquals(1, robot.m_testInitCount.get()); - assertEquals(isLW, LiveWindow.isEnabled()); - - assertThrows(ConcurrentModificationException.class, () -> robot.enableLiveWindowInTest(isLW)); assertEquals(2, robot.m_robotPeriodicCount.get()); assertEquals(2, robot.m_simulationPeriodicCount.get()); @@ -483,7 +471,6 @@ void testModeTest(boolean isLW) { assertEquals(0, robot.m_autonomousInitCount.get()); assertEquals(0, robot.m_teleopInitCount.get()); assertEquals(1, robot.m_testInitCount.get()); - assertFalse(LiveWindow.isEnabled()); assertEquals(3, robot.m_robotPeriodicCount.get()); assertEquals(3, robot.m_simulationPeriodicCount.get()); diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/livewindow/LiveWindowTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/livewindow/LiveWindowTest.java deleted file mode 100644 index 869fb8c3765..00000000000 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/livewindow/LiveWindowTest.java +++ /dev/null @@ -1,14 +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. - -package edu.wpi.first.wpilibj.livewindow; - -import edu.wpi.first.wpilibj.UtilityClassTest; - -@SuppressWarnings("PMD.TestClassWithoutTestCases") -class LiveWindowTest extends UtilityClassTest { - LiveWindowTest() { - super(LiveWindow.class); - } -} diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/templates/timeslice/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/templates/timeslice/Robot.java index f33690c12dd..be7221f7a7e 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/templates/timeslice/Robot.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/templates/timeslice/Robot.java @@ -5,7 +5,6 @@ package edu.wpi.first.wpilibj.templates.timeslice; import edu.wpi.first.wpilibj.TimesliceRobot; -import edu.wpi.first.wpilibj.livewindow.LiveWindow; import edu.wpi.first.wpilibj.smartdashboard.SendableChooser; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; @@ -25,10 +24,6 @@ public Robot() { // Run robot periodic() functions for 5 ms, and run controllers every 10 ms super(0.005, 0.01); - // LiveWindow causes drastic overruns in robot periodic functions that will - // interfere with controllers - LiveWindow.disableAllTelemetry(); - // Runs for 2 ms after robot periodic functions schedule(() -> {}, 0.002); diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/templates/timesliceskeleton/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/templates/timesliceskeleton/Robot.java index d0a019efa19..665018ebc45 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/templates/timesliceskeleton/Robot.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/templates/timesliceskeleton/Robot.java @@ -5,7 +5,6 @@ package edu.wpi.first.wpilibj.templates.timesliceskeleton; import edu.wpi.first.wpilibj.TimesliceRobot; -import edu.wpi.first.wpilibj.livewindow.LiveWindow; /** * The methods in this class are called automatically corresponding to each mode, as described in @@ -18,10 +17,6 @@ public Robot() { // Run robot periodic() functions for 5 ms, and run controllers every 10 ms super(0.005, 0.01); - // LiveWindow causes drastic overruns in robot periodic functions that will - // interfere with controllers - LiveWindow.disableAllTelemetry(); - // Runs for 2 ms after robot periodic functions schedule(() -> {}, 0.002); diff --git a/wpimath/src/main/java/edu/wpi/first/math/controller/BangBangController.java b/wpimath/src/main/java/edu/wpi/first/math/controller/BangBangController.java index b4d56996c06..3151e104b12 100644 --- a/wpimath/src/main/java/edu/wpi/first/math/controller/BangBangController.java +++ b/wpimath/src/main/java/edu/wpi/first/math/controller/BangBangController.java @@ -43,7 +43,7 @@ public BangBangController(double tolerance) { setTolerance(tolerance); - SendableRegistry.addLW(this, "BangBangController", instances); + SendableRegistry.add(this, "BangBangController", instances); MathSharedStore.reportUsage(MathUsageId.kController_BangBangController, instances); } diff --git a/wpimath/src/main/java/edu/wpi/first/math/controller/PIDController.java b/wpimath/src/main/java/edu/wpi/first/math/controller/PIDController.java index 0bd71d4b187..dfdf4a2d3c9 100644 --- a/wpimath/src/main/java/edu/wpi/first/math/controller/PIDController.java +++ b/wpimath/src/main/java/edu/wpi/first/math/controller/PIDController.java @@ -109,7 +109,7 @@ public PIDController(double kp, double ki, double kd, double period) { m_period = period; instances++; - SendableRegistry.addLW(this, "PIDController", instances); + SendableRegistry.add(this, "PIDController", instances); MathSharedStore.reportUsage(MathUsageId.kController_PIDController2, instances); } diff --git a/wpiutil/src/main/java/edu/wpi/first/util/sendable/SendableBuilder.java b/wpiutil/src/main/java/edu/wpi/first/util/sendable/SendableBuilder.java index ee93725acd1..748f38508d9 100644 --- a/wpiutil/src/main/java/edu/wpi/first/util/sendable/SendableBuilder.java +++ b/wpiutil/src/main/java/edu/wpi/first/util/sendable/SendableBuilder.java @@ -42,14 +42,6 @@ enum BackendKind { */ void setActuator(boolean value); - /** - * Set the function that should be called to set the Sendable into a safe state. This is called - * when entering and exiting Live Window mode. - * - * @param func function - */ - void setSafeState(Runnable func); - /** * Add a boolean property. * diff --git a/wpiutil/src/main/java/edu/wpi/first/util/sendable/SendableRegistry.java b/wpiutil/src/main/java/edu/wpi/first/util/sendable/SendableRegistry.java index 025b802094d..7aaa512be40 100644 --- a/wpiutil/src/main/java/edu/wpi/first/util/sendable/SendableRegistry.java +++ b/wpiutil/src/main/java/edu/wpi/first/util/sendable/SendableRegistry.java @@ -5,17 +5,13 @@ package edu.wpi.first.util.sendable; import java.lang.ref.WeakReference; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.WeakHashMap; -import java.util.function.Consumer; -import java.util.function.Supplier; /** * The SendableRegistry class is the public interface for registering sensors and actuators for use - * on dashboards and LiveWindow. + * on dashboards. */ @SuppressWarnings("PMD.AvoidCatchingGenericException") public final class SendableRegistry { @@ -40,8 +36,6 @@ public void close() throws Exception { SendableBuilder m_builder; String m_name; String m_subsystem = "Ungrouped"; - WeakReference m_parent; - boolean m_liveWindow; AutoCloseable[] m_data; void setName(String moduleType, int channel) { @@ -53,7 +47,6 @@ void setName(String moduleType, int moduleNumber, int channel) { } } - private static Supplier liveWindowFactory; private static final Map components = new WeakHashMap<>(); private static int nextDataHandle; @@ -74,15 +67,6 @@ private SendableRegistry() { throw new UnsupportedOperationException("This is a utility class!"); } - /** - * Sets the factory for LiveWindow builders. - * - * @param factory factory function - */ - public static synchronized void setLiveWindowBuilderFactory(Supplier factory) { - liveWindowFactory = factory; - } - /** * Adds an object to the registry. * @@ -133,100 +117,6 @@ public static synchronized void add(Sendable sendable, String subsystem, String comp.m_subsystem = subsystem; } - /** - * Adds an object to the registry and LiveWindow. - * - * @param sendable object to add - * @param name component name - */ - public static synchronized void addLW(Sendable sendable, String name) { - Component comp = getOrAdd(sendable); - if (liveWindowFactory != null) { - if (comp.m_builder != null) { - try { - comp.m_builder.close(); - } catch (Exception e) { - // ignore - } - } - comp.m_builder = liveWindowFactory.get(); - } - comp.m_liveWindow = true; - comp.m_name = name; - } - - /** - * Adds an object to the registry and LiveWindow. - * - * @param sendable object to add - * @param moduleType A string that defines the module name in the label for the value - * @param channel The channel number the device is plugged into - */ - public static synchronized void addLW(Sendable sendable, String moduleType, int channel) { - Component comp = getOrAdd(sendable); - if (liveWindowFactory != null) { - if (comp.m_builder != null) { - try { - comp.m_builder.close(); - } catch (Exception e) { - // ignore - } - } - comp.m_builder = liveWindowFactory.get(); - } - comp.m_liveWindow = true; - comp.setName(moduleType, channel); - } - - /** - * Adds an object to the registry and LiveWindow. - * - * @param sendable object to add - * @param moduleType A string that defines the module name in the label for the value - * @param moduleNumber The number of the particular module type - * @param channel The channel number the device is plugged into - */ - public static synchronized void addLW( - Sendable sendable, String moduleType, int moduleNumber, int channel) { - Component comp = getOrAdd(sendable); - if (liveWindowFactory != null) { - if (comp.m_builder != null) { - try { - comp.m_builder.close(); - } catch (Exception e) { - // ignore - } - } - comp.m_builder = liveWindowFactory.get(); - } - comp.m_liveWindow = true; - comp.setName(moduleType, moduleNumber, channel); - } - - /** - * Adds an object to the registry and LiveWindow. - * - * @param sendable object to add - * @param subsystem subsystem name - * @param name component name - */ - public static synchronized void addLW(Sendable sendable, String subsystem, String name) { - Component comp = getOrAdd(sendable); - if (liveWindowFactory != null) { - if (comp.m_builder != null) { - try { - comp.m_builder.close(); - } catch (Exception e) { - // ignore - } - } - comp.m_builder = liveWindowFactory.get(); - } - comp.m_liveWindow = true; - comp.m_name = name; - comp.m_subsystem = subsystem; - } - /** * Adds a child object to an object. Adds the child object to the registry if it's not already * present. @@ -240,7 +130,7 @@ public static synchronized void addChild(Sendable parent, Object child) { comp = new Component(); components.put(child, comp); } - comp.m_parent = new WeakReference<>(parent); + // comp.m_parent = new WeakReference<>(parent); } /** @@ -430,30 +320,6 @@ public static synchronized Object getData(Sendable sendable, int handle) { return comp.m_data[handle]; } - /** - * Enables LiveWindow for an object. - * - * @param sendable object - */ - public static synchronized void enableLiveWindow(Sendable sendable) { - Component comp = components.get(sendable); - if (comp != null) { - comp.m_liveWindow = true; - } - } - - /** - * Disables LiveWindow for an object. - * - * @param sendable object - */ - public static synchronized void disableLiveWindow(Sendable sendable) { - Component comp = components.get(sendable); - if (comp != null) { - comp.m_liveWindow = false; - } - } - /** * Publishes an object in the registry to a builder. * @@ -485,98 +351,4 @@ public static synchronized void update(Sendable sendable) { comp.m_builder.update(); } } - - /** Data passed to foreachLiveWindow() callback function. */ - @SuppressWarnings("MemberName") - public static class CallbackData { - /** Sendable object. */ - public Sendable sendable; - - /** Name. */ - public String name; - - /** Subsystem. */ - public String subsystem; - - /** Parent sendable object. */ - public Sendable parent; - - /** Data stored in object with setData(). Update this to change the data. */ - public AutoCloseable data; - - /** Sendable builder for the sendable. */ - public SendableBuilder builder; - - /** Default constructor. */ - public CallbackData() {} - } - - // As foreachLiveWindow is single threaded, cache the components it - // iterates over to avoid risk of ConcurrentModificationException - private static List foreachComponents = new ArrayList<>(); - - /** - * Iterates over LiveWindow-enabled objects in the registry. It is *not* safe to call other - * SendableRegistry functions from the callback. - * - * @param dataHandle data handle to get data object passed to callback - * @param callback function to call for each object - */ - @SuppressWarnings("PMD.CompareObjectsWithEquals") - public static synchronized void foreachLiveWindow( - int dataHandle, Consumer callback) { - CallbackData cbdata = new CallbackData(); - foreachComponents.clear(); - foreachComponents.addAll(components.values()); - for (Component comp : foreachComponents) { - if (comp.m_builder == null || comp.m_sendable == null) { - continue; - } - cbdata.sendable = comp.m_sendable.get(); - if (cbdata.sendable != null && comp.m_liveWindow) { - cbdata.name = comp.m_name; - cbdata.subsystem = comp.m_subsystem; - if (comp.m_parent != null) { - cbdata.parent = comp.m_parent.get(); - } else { - cbdata.parent = null; - } - if (comp.m_data != null && dataHandle < comp.m_data.length) { - cbdata.data = comp.m_data[dataHandle]; - } else { - cbdata.data = null; - } - cbdata.builder = comp.m_builder; - try { - callback.accept(cbdata); - } catch (Throwable throwable) { - Throwable cause = throwable.getCause(); - if (cause != null) { - throwable = cause; - } - System.err.println("Unhandled exception calling LiveWindow for " + comp.m_name + ": "); - throwable.printStackTrace(); - comp.m_liveWindow = false; - } - if (cbdata.data != null) { - if (comp.m_data == null) { - comp.m_data = new AutoCloseable[dataHandle + 1]; - } else if (dataHandle >= comp.m_data.length) { - comp.m_data = Arrays.copyOf(comp.m_data, dataHandle + 1); - } - if (comp.m_data[dataHandle] != cbdata.data) { - if (comp.m_data[dataHandle] != null) { - try { - comp.m_data[dataHandle].close(); - } catch (Exception e) { - // ignore - } - } - comp.m_data[dataHandle] = cbdata.data; - } - } - } - } - foreachComponents.clear(); - } } diff --git a/wpiutil/src/main/native/cpp/sendable/SendableRegistry.cpp b/wpiutil/src/main/native/cpp/sendable/SendableRegistry.cpp index 99ff7f5e1ab..74ec0e9e5a7 100644 --- a/wpiutil/src/main/native/cpp/sendable/SendableRegistry.cpp +++ b/wpiutil/src/main/native/cpp/sendable/SendableRegistry.cpp @@ -26,7 +26,6 @@ struct Component { std::string name; std::string subsystem = "Ungrouped"; Sendable* parent = nullptr; - bool liveWindow = false; wpi::SmallVector, 2> data; void SetName(std::string_view moduleType, int channel) { @@ -41,7 +40,6 @@ struct Component { struct SendableRegistryInst { wpi::recursive_mutex mutex; - std::function()> liveWindowFactory; wpi::UidVector, 32> components; wpi::DenseMap componentMap; int nextDataHandle = 0; @@ -85,11 +83,6 @@ void SendableRegistry::EnsureInitialized() { GetInstance(); } -void SendableRegistry::SetLiveWindowBuilderFactory( - std::function()> factory) { - GetInstance().liveWindowFactory = std::move(factory); -} - void SendableRegistry::Add(Sendable* sendable, std::string_view name) { auto& inst = GetInstance(); std::scoped_lock lock(inst.mutex); @@ -126,58 +119,6 @@ void SendableRegistry::Add(Sendable* sendable, std::string_view subsystem, comp.subsystem = subsystem; } -void SendableRegistry::AddLW(Sendable* sendable, std::string_view name) { - auto& inst = GetInstance(); - std::scoped_lock lock(inst.mutex); - auto& comp = inst.GetOrAdd(sendable); - comp.sendable = sendable; - if (inst.liveWindowFactory) { - comp.builder = inst.liveWindowFactory(); - } - comp.liveWindow = true; - comp.name = name; -} - -void SendableRegistry::AddLW(Sendable* sendable, std::string_view moduleType, - int channel) { - auto& inst = GetInstance(); - std::scoped_lock lock(inst.mutex); - auto& comp = inst.GetOrAdd(sendable); - comp.sendable = sendable; - if (inst.liveWindowFactory) { - comp.builder = inst.liveWindowFactory(); - } - comp.liveWindow = true; - comp.SetName(moduleType, channel); -} - -void SendableRegistry::AddLW(Sendable* sendable, std::string_view moduleType, - int moduleNumber, int channel) { - auto& inst = GetInstance(); - std::scoped_lock lock(inst.mutex); - auto& comp = inst.GetOrAdd(sendable); - comp.sendable = sendable; - if (inst.liveWindowFactory) { - comp.builder = inst.liveWindowFactory(); - } - comp.liveWindow = true; - comp.SetName(moduleType, moduleNumber, channel); -} - -void SendableRegistry::AddLW(Sendable* sendable, std::string_view subsystem, - std::string_view name) { - auto& inst = GetInstance(); - std::scoped_lock lock(inst.mutex); - auto& comp = inst.GetOrAdd(sendable); - comp.sendable = sendable; - if (inst.liveWindowFactory) { - comp.builder = inst.liveWindowFactory(); - } - comp.liveWindow = true; - comp.name = name; - comp.subsystem = subsystem; -} - void SendableRegistry::AddChild(Sendable* parent, Sendable* child) { auto& inst = GetInstance(); std::scoped_lock lock(inst.mutex); @@ -361,26 +302,6 @@ std::shared_ptr SendableRegistry::GetData(Sendable* sendable, return comp.data[handle]; } -void SendableRegistry::EnableLiveWindow(Sendable* sendable) { - auto& inst = GetInstance(); - std::scoped_lock lock(inst.mutex); - auto it = inst.componentMap.find(sendable); - if (it == inst.componentMap.end() || !inst.components[it->getSecond() - 1]) { - return; - } - inst.components[it->getSecond() - 1]->liveWindow = true; -} - -void SendableRegistry::DisableLiveWindow(Sendable* sendable) { - auto& inst = GetInstance(); - std::scoped_lock lock(inst.mutex); - auto it = inst.componentMap.find(sendable); - if (it == inst.componentMap.end() || !inst.components[it->getSecond() - 1]) { - return; - } - inst.components[it->getSecond() - 1]->liveWindow = false; -} - SendableRegistry::UID SendableRegistry::GetUniqueId(Sendable* sendable) { auto& inst = GetInstance(); std::scoped_lock lock(inst.mutex); @@ -430,25 +351,3 @@ void SendableRegistry::Update(UID sendableUid) { inst.components[sendableUid - 1]->builder->Update(); } } - -void SendableRegistry::ForeachLiveWindow( - int dataHandle, wpi::function_ref callback) { - auto& inst = GetInstance(); - assert(dataHandle >= 0); - std::scoped_lock lock(inst.mutex); - wpi::SmallVector components; - for (auto&& comp : inst.components) { - components.emplace_back(comp.get()); - } - for (auto comp : components) { - if (comp && comp->builder && comp->sendable && comp->liveWindow) { - if (static_cast(dataHandle) >= comp->data.size()) { - comp->data.resize(dataHandle + 1); - } - CallbackData cbdata{comp->sendable, comp->name, - comp->subsystem, comp->parent, - comp->data[dataHandle], *comp->builder}; - callback(cbdata); - } - } -} diff --git a/wpiutil/src/main/native/include/wpi/sendable/SendableBuilder.h b/wpiutil/src/main/native/include/wpi/sendable/SendableBuilder.h index 1913d7cc72f..5b7d29f409c 100644 --- a/wpiutil/src/main/native/include/wpi/sendable/SendableBuilder.h +++ b/wpiutil/src/main/native/include/wpi/sendable/SendableBuilder.h @@ -48,14 +48,6 @@ class SendableBuilder { */ virtual void SetActuator(bool value) = 0; - /** - * Set the function that should be called to set the Sendable into a safe - * state. This is called when entering and exiting Live Window mode. - * - * @param func function - */ - virtual void SetSafeState(std::function func) = 0; - /** * Add a boolean property. * diff --git a/wpiutil/src/main/native/include/wpi/sendable/SendableRegistry.h b/wpiutil/src/main/native/include/wpi/sendable/SendableRegistry.h index 37ed45fe192..324c7d286ad 100644 --- a/wpiutil/src/main/native/include/wpi/sendable/SendableRegistry.h +++ b/wpiutil/src/main/native/include/wpi/sendable/SendableRegistry.h @@ -4,13 +4,10 @@ #pragma once -#include #include #include #include -#include "wpi/function_ref.h" - namespace wpi { class Sendable; @@ -18,7 +15,7 @@ class SendableBuilder; /** * The SendableRegistry class is the public interface for registering sensors - * and actuators for use on dashboards and LiveWindow. + * and actuators for use on dashboards. */ class SendableRegistry final { public: @@ -32,14 +29,6 @@ class SendableRegistry final { */ static void EnsureInitialized(); - /** - * Sets the factory for LiveWindow builders. - * - * @param factory factory function - */ - static void SetLiveWindowBuilderFactory( - std::function()> factory); - /** * Adds an object to the registry. * @@ -80,47 +69,6 @@ class SendableRegistry final { static void Add(Sendable* sendable, std::string_view subsystem, std::string_view name); - /** - * Adds an object to the registry and LiveWindow. - * - * @param sendable object to add - * @param name component name - */ - static void AddLW(Sendable* sendable, std::string_view name); - - /** - * Adds an object to the registry and LiveWindow. - * - * @param sendable object to add - * @param moduleType A string that defines the module name in the label for - * the value - * @param channel The channel number the device is plugged into - */ - static void AddLW(Sendable* sendable, std::string_view moduleType, - int channel); - - /** - * Adds an object to the registry and LiveWindow. - * - * @param sendable object to add - * @param moduleType A string that defines the module name in the label for - * the value - * @param moduleNumber The number of the particular module type - * @param channel The channel number the device is plugged into - */ - static void AddLW(Sendable* sendable, std::string_view moduleType, - int moduleNumber, int channel); - - /** - * Adds an object to the registry and LiveWindow. - * - * @param sendable object to add - * @param subsystem subsystem name - * @param name component name - */ - static void AddLW(Sendable* sendable, std::string_view subsystem, - std::string_view name); - /** * Adds a child object to an object. Adds the child object to the registry * if it's not already present. @@ -255,20 +203,6 @@ class SendableRegistry final { */ static std::shared_ptr GetData(Sendable* sendable, int handle); - /** - * Enables LiveWindow for an object. - * - * @param sendable object - */ - static void EnableLiveWindow(Sendable* sendable); - - /** - * Disables LiveWindow for an object. - * - * @param sendable object - */ - static void DisableLiveWindow(Sendable* sendable); - /** * Get unique id for an object. Since objects can move, use this instead * of storing Sendable* directly if ownership is in question. @@ -301,39 +235,6 @@ class SendableRegistry final { * @param sendableUid sendable unique id */ static void Update(UID sendableUid); - - /** - * Data passed to ForeachLiveWindow() callback function - */ - struct CallbackData { - CallbackData(Sendable* sendable_, std::string_view name_, - std::string_view subsystem_, wpi::Sendable* parent_, - std::shared_ptr& data_, SendableBuilder& builder_) - : sendable(sendable_), - name(name_), - subsystem(subsystem_), - parent(parent_), - data(data_), - builder(builder_) {} - - Sendable* sendable; - std::string_view name; - std::string_view subsystem; - Sendable* parent; - std::shared_ptr& data; - SendableBuilder& builder; - }; - - /** - * Iterates over LiveWindow-enabled objects in the registry. - * It is *not* safe to call other SendableRegistry functions from the - * callback (this will likely deadlock). - * - * @param dataHandle data handle to get data pointer passed to callback - * @param callback function to call for each object - */ - static void ForeachLiveWindow( - int dataHandle, wpi::function_ref callback); }; } // namespace wpi From 3b345fe21867a63a5fcec18221ac138493b1ef38 Mon Sep 17 00:00:00 2001 From: PJ Reiniger Date: Sun, 26 Jan 2025 19:52:33 -0500 Subject: [PATCH 6/6] [bazel] Add macros to build jni code and java tests (#7693) --- .github/workflows/bazel.yml | 1 + .styleguide | 1 + WORKSPACE | 67 ++++++++++++++++++++ apriltag/BUILD.bazel | 31 ++++++++- cscore/BUILD.bazel | 26 +++++++- epilogue-processor/BUILD.bazel | 13 ++++ epilogue-runtime/BUILD.bazel | 10 +++ fieldImages/BUILD.bazel | 9 +++ hal/BUILD.bazel | 42 ++++++++----- ntcore/BUILD.bazel | 33 +++++++++- shared/bazel/rules/BUILD.bazel | 0 shared/bazel/rules/java_rules.bzl | 35 +++++++++++ shared/bazel/rules/jni_rules.bzl | 101 ++++++++++++++++++++++++++++++ wpilibNewCommands/BUILD.bazel | 18 ++++++ wpilibj/BUILD.bazel | 16 +++++ wpimath/BUILD.bazel | 30 ++++++++- wpinet/BUILD.bazel | 28 ++++++++- wpiunits/BUILD.bazel | 9 +++ wpiutil/BUILD.bazel | 25 +++++++- 19 files changed, 468 insertions(+), 27 deletions(-) create mode 100644 shared/bazel/rules/BUILD.bazel create mode 100644 shared/bazel/rules/java_rules.bzl create mode 100644 shared/bazel/rules/jni_rules.bzl diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index a2f0c381d6f..8949d6b055d 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -57,6 +57,7 @@ jobs: matrix: include: - { name: "Linux (native)", os: ubuntu-24.04, action: "test", config: "--config=linux", } + - { name: "Linux (systemcore)", os: ubuntu-24.04, action: "build", config: "--config=systemcore", } name: "${{ matrix.name }}" runs-on: ${{ matrix.os }} steps: diff --git a/.styleguide b/.styleguide index feb5dc3e00e..a23842e2f53 100644 --- a/.styleguide +++ b/.styleguide @@ -14,6 +14,7 @@ modifiableFileExclude { thirdparty/ \.patch$ gradlew + BUILD.bazel } generatedFileExclude { diff --git a/WORKSPACE b/WORKSPACE index eb731acfd2a..7362421731f 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -13,6 +13,7 @@ load("@rules_jvm_external//:repositories.bzl", "rules_jvm_external_deps") rules_jvm_external_deps() load("@rules_jvm_external//:defs.bzl", "maven_install") +load("@rules_jvm_external//:specs.bzl", "maven") maven_artifacts = [ "org.ejml:ejml-simple:0.43.1", @@ -21,6 +22,72 @@ maven_artifacts = [ "com.fasterxml.jackson.core:jackson-databind:2.15.2", "us.hebi.quickbuf:quickbuf-runtime:1.3.3", "com.google.code.gson:gson:2.10.1", + maven.artifact( + "org.junit.jupiter", + "junit-jupiter", + "5.10.1", + testonly = True, + ), + maven.artifact( + "org.junit.platform", + "junit-platform-console", + "1.10.1", + testonly = True, + ), + maven.artifact( + "org.junit.platform", + "junit-platform-launcher", + "1.10.1", + testonly = True, + ), + maven.artifact( + "org.junit.platform", + "junit-platform-reporting", + "1.10.1", + testonly = True, + ), + maven.artifact( + "com.google.code.gson", + "gson", + "2.10.1", + testonly = False, + ), + maven.artifact( + "org.hamcrest", + "hamcrest-all", + "1.3", + testonly = True, + ), + maven.artifact( + "com.googlecode.junit-toolbox", + "junit-toolbox", + "2.4", + testonly = True, + ), + maven.artifact( + "org.apache.ant", + "ant", + "1.10.12", + testonly = True, + ), + maven.artifact( + "org.apache.ant", + "ant-junit", + "1.10.12", + testonly = True, + ), + maven.artifact( + "org.mockito", + "mockito-core", + "4.1.0", + testonly = True, + ), + maven.artifact( + "com.google.testing.compile", + "compile-testing", + "0.21.0", + testonly = True, + ), ] maven_install( diff --git a/apriltag/BUILD.bazel b/apriltag/BUILD.bazel index ea1ef1abe00..3544d27ef0a 100644 --- a/apriltag/BUILD.bazel +++ b/apriltag/BUILD.bazel @@ -1,6 +1,8 @@ load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") -load("@rules_java//java:defs.bzl", "java_binary", "java_library") +load("@rules_java//java:defs.bzl", "java_binary") load("@rules_python//python:defs.bzl", "py_binary") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") +load("//shared/bazel/rules:jni_rules.bzl", "wpilib_jni_cc_library", "wpilib_jni_java_library") load("//shared/bazel/rules/gen:gen-resources.bzl", "generate_resources") cc_library( @@ -59,9 +61,20 @@ cc_library( ], ) -java_library( +wpilib_jni_cc_library( + name = "apriltagjni", + srcs = glob(["src/main/native/cpp/jni/**"]), + java_dep = ":apriltag-java", + visibility = ["//visibility:public"], + deps = [ + ":apriltag.static", + ], +) + +wpilib_jni_java_library( name = "apriltag-java", srcs = glob(["src/main/java/**/*.java"]), + native_libs = [":apriltagjni"], resource_strip_prefix = "apriltag/src/main/native/resources", resources = glob(["src/main/native/resources/**"]), visibility = ["//visibility:public"], @@ -88,6 +101,20 @@ cc_test( ], ) +wpilib_java_junit5_test( + name = "apriltag-java-test", + srcs = glob(["src/test/java/**/*.java"]), + resource_strip_prefix = "apriltag/src/test/resources", + resources = glob(["src/test/resources/**"]), + deps = [ + ":apriltag-java", + "//wpimath:wpimath-java", + "//wpiutil:wpiutil-java", + "@bzlmodrio-opencv//libraries/java/opencv", + "@maven//:com_fasterxml_jackson_core_jackson_databind", + ], +) + cc_binary( name = "DevMain-Cpp", srcs = ["src/dev/native/cpp/main.cpp"], diff --git a/cscore/BUILD.bazel b/cscore/BUILD.bazel index d40fb4d2fd9..1c0ac8d9b7c 100644 --- a/cscore/BUILD.bazel +++ b/cscore/BUILD.bazel @@ -1,5 +1,7 @@ load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test", "objc_library") -load("@rules_java//java:defs.bzl", "java_binary", "java_library") +load("@rules_java//java:defs.bzl", "java_binary") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") +load("//shared/bazel/rules:jni_rules.bzl", "wpilib_jni_cc_library", "wpilib_jni_java_library") WIN_SRCS = glob([ "src/main/native/windows/**/*.cpp", @@ -71,9 +73,20 @@ cc_library( }), ) -java_library( +wpilib_jni_cc_library( + name = "cscorejni", + srcs = glob(["src/main/native/cpp/jni/**"]), + java_dep = ":cscore-java", + visibility = ["//visibility:public"], + deps = [ + ":cscore.static", + ], +) + +wpilib_jni_java_library( name = "cscore-java", srcs = glob(["src/main/java/**/*.java"]), + native_libs = [":cscorejni"], visibility = ["//visibility:public"], deps = [ "//wpiutil:wpiutil-java", @@ -91,6 +104,15 @@ cc_test( ], ) +wpilib_java_junit5_test( + name = "cscore-java-test", + srcs = glob(["src/test/java/**/*.java"]), + deps = [ + ":cscore-java", + "//wpiutil:wpiutil-java", + ], +) + cc_binary( name = "DevMain-Cpp", srcs = ["src/dev/native/cpp/main.cpp"], diff --git a/epilogue-processor/BUILD.bazel b/epilogue-processor/BUILD.bazel index a9a8e083ab4..290132009d0 100644 --- a/epilogue-processor/BUILD.bazel +++ b/epilogue-processor/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_java//java:defs.bzl", "java_library", "java_plugin") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") java_library( name = "processor", @@ -20,3 +21,15 @@ java_plugin( ":processor", ], ) + +wpilib_java_junit5_test( + name = "processor-test", + srcs = glob(["src/test/java/**/*.java"]), + plugins = [ + ":plugin", + ], + deps = [ + ":processor", + "@maven//:com_google_testing_compile_compile_testing", + ], +) diff --git a/epilogue-runtime/BUILD.bazel b/epilogue-runtime/BUILD.bazel index 05db6b75270..6e02a5dfcb8 100644 --- a/epilogue-runtime/BUILD.bazel +++ b/epilogue-runtime/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_java//java:defs.bzl", "java_library") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") java_library( name = "epilogue", @@ -10,3 +11,12 @@ java_library( "//wpiutil:wpiutil-java", ], ) + +wpilib_java_junit5_test( + name = "epilogue-test", + srcs = glob(["src/test/java/**/*.java"]), + deps = [ + ":epilogue", + "//wpiutil:wpiutil-java", + ], +) diff --git a/fieldImages/BUILD.bazel b/fieldImages/BUILD.bazel index b5cfc82cfa4..e006e9ef83c 100644 --- a/fieldImages/BUILD.bazel +++ b/fieldImages/BUILD.bazel @@ -1,5 +1,6 @@ load("@rules_cc//cc:defs.bzl", "cc_library") load("@rules_java//java:defs.bzl", "java_library") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") load("//shared/bazel/rules/gen:gen-resources.bzl", "generate_resources") generate_resources( @@ -29,3 +30,11 @@ java_library( "@maven//:com_fasterxml_jackson_core_jackson_databind", ], ) + +wpilib_java_junit5_test( + name = "fieldImages-test", + srcs = glob(["src/test/java/**/*.java"]), + deps = [ + ":fieldImages-java", + ], +) diff --git a/hal/BUILD.bazel b/hal/BUILD.bazel index 6f8097b070f..2a1c00a1fc6 100644 --- a/hal/BUILD.bazel +++ b/hal/BUILD.bazel @@ -1,5 +1,7 @@ load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") -load("@rules_java//java:defs.bzl", "java_binary", "java_library") +load("@rules_java//java:defs.bzl", "java_binary") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") +load("//shared/bazel/rules:jni_rules.bzl", "wpilib_jni_cc_library", "wpilib_jni_java_library") cc_library( name = "generated_cc_headers", @@ -31,23 +33,14 @@ filegroup( visibility = ["//hal:__subpackages__"], ) -ATHENA_SRCS = glob(["src/main/native/athena/**"]) - -ATHENA_DEPS = ["@bzlmodrio-ni//libraries/cpp/ni:shared"] +SYSTEMCORE_SRCS = glob(["src/main/native/systemcore/**"]) SIM_SRCS = glob(["src/main/native/sim/**"]) -SIM_DEPS = [] - -HAL_DEPS = select({ - "@rules_bzlmodrio_toolchains//constraints/is_roborio:roborio": ATHENA_DEPS, - "//conditions:default": SIM_DEPS, -}) - filegroup( name = "platform-srcs", srcs = select({ - "@rules_bzlmodrio_toolchains//constraints/is_roborio:roborio": ATHENA_SRCS, + "@rules_bzlmodrio_toolchains//constraints/is_systemcore:systemcore": SYSTEMCORE_SRCS, "//conditions:default": SIM_SRCS, }), ) @@ -67,17 +60,28 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":generated_cc_headers", - ":mrc_cc_headers", ":generated_mrc_cc_headers", + ":mrc_cc_headers", "//ntcore:ntcore.static", "//wpinet:wpinet.static", "//wpiutil:wpiutil.static", - ] + HAL_DEPS, + ], +) + +wpilib_jni_cc_library( + name = "wpiHaljni", + srcs = glob(["src/main/native/cpp/jni/**"]), + java_dep = ":hal-java", + visibility = ["//visibility:public"], + deps = [ + ":wpiHal.static", + ], ) -java_library( +wpilib_jni_java_library( name = "hal-java", srcs = [":generated_java"] + glob(["src/main/java/**/*.java"]), + native_libs = [":wpiHaljni"], visibility = ["//visibility:public"], deps = [ "//ntcore:networktables-java", @@ -99,6 +103,14 @@ cc_test( ], ) +wpilib_java_junit5_test( + name = "hal-java-test", + srcs = glob(["src/test/java/**/*.java"]), + deps = [ + ":hal-java", + ], +) + cc_binary( name = "DevMain-Cpp", srcs = ["src/dev/native/cpp/main.cpp"], diff --git a/ntcore/BUILD.bazel b/ntcore/BUILD.bazel index 1156cff691e..9b020297c59 100644 --- a/ntcore/BUILD.bazel +++ b/ntcore/BUILD.bazel @@ -1,5 +1,7 @@ load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") -load("@rules_java//java:defs.bzl", "java_binary", "java_library") +load("@rules_java//java:defs.bzl", "java_binary") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") +load("//shared/bazel/rules:jni_rules.bzl", "wpilib_jni_cc_library", "wpilib_jni_java_library") cc_library( name = "generated_cc_headers", @@ -18,6 +20,12 @@ filegroup( visibility = ["//ntcore:__subpackages__"], ) +filegroup( + name = "generated_jni", + srcs = glob(["src/generated/main/native/cpp/jni/**"]), + visibility = ["//ntcore:__subpackages__"], +) + filegroup( name = "generated_java", srcs = glob(["src/generated/main/java/**/*.java"]), @@ -44,9 +52,20 @@ cc_library( ], ) -java_library( +wpilib_jni_cc_library( + name = "ntcorejni", + srcs = glob(["src/main/native/cpp/jni/**"]) + [":generated_jni"], + java_dep = ":networktables-java", + visibility = ["//visibility:public"], + deps = [ + ":ntcore.static", + ], +) + +wpilib_jni_java_library( name = "networktables-java", srcs = glob(["src/main/java/**/*.java"]) + [":generated_java"], + native_libs = [":ntcorejni"], visibility = ["//visibility:public"], deps = [ "//wpiutil:wpiutil-java", @@ -73,6 +92,16 @@ cc_test( ], ) +wpilib_java_junit5_test( + name = "ntcore-java-test", + srcs = glob(["src/test/java/**/*.java"]), + tags = ["exclusive"], + deps = [ + ":networktables-java", + "//wpiutil:wpiutil-java", + ], +) + cc_binary( name = "DevMain-Cpp", srcs = ["src/dev/native/cpp/main.cpp"], diff --git a/shared/bazel/rules/BUILD.bazel b/shared/bazel/rules/BUILD.bazel new file mode 100644 index 00000000000..e69de29bb2d diff --git a/shared/bazel/rules/java_rules.bzl b/shared/bazel/rules/java_rules.bzl new file mode 100644 index 00000000000..b712c0cb7c1 --- /dev/null +++ b/shared/bazel/rules/java_rules.bzl @@ -0,0 +1,35 @@ +load("@rules_java//java:defs.bzl", "java_binary") + +def wpilib_java_junit5_test( + name, + deps = [], + runtime_deps = [], + args = [], + tags = [], + package = "edu", + **kwargs): + """ + Convenience helper to make a junit5 test + """ + junit_deps = [ + "@maven//:org_junit_jupiter_junit_jupiter_api", + "@maven//:org_junit_jupiter_junit_jupiter_params", + "@maven//:org_junit_jupiter_junit_jupiter_engine", + ] + + junit_runtime_deps = [ + "@maven//:org_junit_platform_junit_platform_console", + ] + + # TODO - replace with java_test once shared libraries are hooked up. + java_binary( + name = name, + deps = deps + junit_deps, + runtime_deps = runtime_deps + junit_runtime_deps, + args = args + ["--select-package", package], + main_class = "org.junit.platform.console.ConsoleLauncher", + use_testrunner = False, + testonly = True, + tags = tags + ["no-roborio", "no-bionic", "no-raspbian", "allwpilib-build-java", "no-asan", "no-tsan", "no-ubsan"], + **kwargs + ) diff --git a/shared/bazel/rules/jni_rules.bzl b/shared/bazel/rules/jni_rules.bzl new file mode 100644 index 00000000000..dfc23dbb481 --- /dev/null +++ b/shared/bazel/rules/jni_rules.bzl @@ -0,0 +1,101 @@ +load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") +load("@rules_cc//cc:defs.bzl", "cc_library") +load("@rules_java//java:defs.bzl", "java_library") + +def _jni_headers_impl(ctx): + include_dir = ctx.actions.declare_directory(ctx.attr.name + ".h") + native_headers_jar = ctx.attr.lib[JavaInfo].outputs.native_headers + args = ["xf", native_headers_jar.path, "-d", include_dir.path] + + ctx.actions.run( + inputs = [native_headers_jar], + tools = [ctx.executable._zipper], + outputs = [include_dir], + executable = ctx.executable._zipper.path, + arguments = args, + ) + + cc_toolchain = find_cpp_toolchain(ctx) + feature_configuration = cc_common.configure_features( + ctx = ctx, + cc_toolchain = cc_toolchain, + requested_features = ctx.features, + unsupported_features = ctx.disabled_features, + ) + compilation_context, _ = cc_common.compile( + name = ctx.attr.name, + actions = ctx.actions, + feature_configuration = feature_configuration, + cc_toolchain = cc_toolchain, + public_hdrs = [include_dir], + quote_includes = [include_dir.path], + ) + cc_info_with_jni = cc_common.merge_cc_infos( + direct_cc_infos = [ + CcInfo(compilation_context = compilation_context), + ctx.attr.jni[CcInfo], + ], + ) + + return [ + DefaultInfo(files = depset([include_dir])), + cc_info_with_jni, + ] + +_jni_headers = rule( + implementation = _jni_headers_impl, + attrs = { + "jni": attr.label(mandatory = True), + "lib": attr.label( + mandatory = True, + providers = [JavaInfo], + ), + "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), + "_zipper": attr.label( + executable = True, + cfg = "exec", + default = Label("@bazel_tools//tools/zip:zipper"), + ), + }, + fragments = ["cpp"], + incompatible_use_toolchain_transition = True, + provides = [CcInfo], + toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], +) + +def wpilib_jni_java_library( + name, + native_libs = [], + **java_library_args): + tags = java_library_args.pop("tags", default = None) + visibility = java_library_args.pop("visibility", default = None) + testonly = java_library_args.pop("testonly", default = None) + headers_name = name + ".hdrs" + java_library( + name = name, + visibility = visibility, + testonly = testonly, + **java_library_args + ) + + jni = "@rules_bzlmodrio_toolchains//jni" + _jni_headers( + name = headers_name, + tags = ["manual"], + jni = jni, + lib = ":" + name, + testonly = testonly, + visibility = visibility, + ) + +def wpilib_jni_cc_library( + name, + deps = [], + java_dep = None, + **kwargs): + jni = "@rules_bzlmodrio_toolchains//jni" + cc_library( + name = name + ".static", + deps = [jni, java_dep + ".hdrs"] + deps, + **kwargs + ) diff --git a/wpilibNewCommands/BUILD.bazel b/wpilibNewCommands/BUILD.bazel index 6add11137ad..37b063dd5bf 100644 --- a/wpilibNewCommands/BUILD.bazel +++ b/wpilibNewCommands/BUILD.bazel @@ -1,5 +1,6 @@ load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") load("@rules_java//java:defs.bzl", "java_binary", "java_library") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") cc_library( name = "generated_cc_headers", @@ -67,6 +68,23 @@ cc_test( ], ) +wpilib_java_junit5_test( + name = "wpilibNewCommands-java-test", + srcs = glob(["**/*.java"]), + resource_strip_prefix = "wpilibNewCommands/src/test/resources", + resources = glob(["src/test/resources/**"]), + deps = [ + ":wpilibNewCommands-java", + "//hal:hal-java", + "//ntcore:networktables-java", + "//wpilibj", + "//wpimath:wpimath-java", + "//wpiunits", + "//wpiutil:wpiutil-java", + "@maven//:org_mockito_mockito_core", + ], +) + cc_binary( name = "DevMain-Cpp", srcs = ["src/dev/native/cpp/main.cpp"], diff --git a/wpilibj/BUILD.bazel b/wpilibj/BUILD.bazel index f0a9359ae91..e5b8b0dd993 100644 --- a/wpilibj/BUILD.bazel +++ b/wpilibj/BUILD.bazel @@ -1,5 +1,6 @@ load("@rules_cc//cc:defs.bzl", "cc_binary") load("@rules_java//java:defs.bzl", "java_binary", "java_library") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") load("//shared/bazel/rules/gen:gen-version-file.bzl", "generate_version_file") generate_version_file( @@ -36,6 +37,21 @@ java_library( ], ) +wpilib_java_junit5_test( + name = "wpilibj-java-test", + srcs = glob(["src/test/java/**/*.java"]), + resource_strip_prefix = "wpilibj/src/test/resources", + resources = glob(["src/test/resources/**"]), + deps = [ + ":wpilibj", + "//hal:hal-java", + "//ntcore:networktables-java", + "//wpimath:wpimath-java", + "//wpiunits", + "//wpiutil:wpiutil-java", + ], +) + cc_binary( name = "DevMain-Cpp", srcs = ["src/dev/native/cpp/main.cpp"], diff --git a/wpimath/BUILD.bazel b/wpimath/BUILD.bazel index 7979a8ba1cb..d6763b68dec 100644 --- a/wpimath/BUILD.bazel +++ b/wpimath/BUILD.bazel @@ -1,6 +1,8 @@ load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") -load("@rules_java//java:defs.bzl", "java_binary", "java_library") +load("@rules_java//java:defs.bzl", "java_binary") load("@rules_python//python:defs.bzl", "py_binary") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") +load("//shared/bazel/rules:jni_rules.bzl", "wpilib_jni_cc_library", "wpilib_jni_java_library") filegroup( name = "generated_java", @@ -78,9 +80,20 @@ cc_library( ], ) -java_library( +wpilib_jni_cc_library( + name = "wpimathjni", + srcs = glob(["src/main/native/cpp/jni/**"]), + java_dep = ":wpimath-java", + visibility = ["//visibility:public"], + deps = [ + ":wpimath.static", + ], +) + +wpilib_jni_java_library( name = "wpimath-java", srcs = [":generated_java"] + glob(["src/main/java/**/*.java"]), + native_libs = [":wpimathjni"], visibility = ["//visibility:public"], deps = [ "//wpiunits", @@ -121,6 +134,19 @@ cc_test( ], ) +wpilib_java_junit5_test( + name = "wpimath-java-test", + srcs = glob(["src/test/java/**/*.java"]), + deps = [ + ":wpimath-java", + "//wpiunits", + "//wpiutil:wpiutil-java", + "@maven//:org_ejml_ejml_core", + "@maven//:org_ejml_ejml_simple", + "@maven//:us_hebi_quickbuf_quickbuf_runtime", + ], +) + cc_binary( name = "DevMain-Cpp", srcs = ["src/dev/native/cpp/main.cpp"], diff --git a/wpinet/BUILD.bazel b/wpinet/BUILD.bazel index c6bdebae7a0..8a56e0b3459 100644 --- a/wpinet/BUILD.bazel +++ b/wpinet/BUILD.bazel @@ -1,5 +1,7 @@ load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") -load("@rules_java//java:defs.bzl", "java_binary", "java_library") +load("@rules_java//java:defs.bzl", "java_binary") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") +load("//shared/bazel/rules:jni_rules.bzl", "wpilib_jni_cc_library", "wpilib_jni_java_library") load("//shared/bazel/rules/gen:gen-resources.bzl", "generate_resources") WIN_UV_SRCS = glob([ @@ -131,9 +133,23 @@ cc_library( ], ) -java_library( +wpilib_jni_cc_library( + name = "wpinetjni", + srcs = glob([ + "src/main/native/cpp/jni/**", + "src/main/native/cpp/**/*.h", + ]), + java_dep = ":wpinet-java", + visibility = ["//visibility:public"], + deps = [ + ":wpinet.static", + ], +) + +wpilib_jni_java_library( name = "wpinet-java", srcs = glob(["src/main/java/**/*.java"]), + native_libs = [":wpinetjni"], visibility = ["//visibility:public"], deps = [ "//wpiutil:wpiutil-java", @@ -155,6 +171,14 @@ cc_test( ], ) +wpilib_java_junit5_test( + name = "wpinet-java-test", + srcs = glob(["src/test/java/**/*.java"]), + deps = [ + ":wpinet-java", + ], +) + cc_binary( name = "DevMain-Cpp", srcs = ["src/dev/native/cpp/main.cpp"], diff --git a/wpiunits/BUILD.bazel b/wpiunits/BUILD.bazel index d6686308a97..d6609a4f00f 100644 --- a/wpiunits/BUILD.bazel +++ b/wpiunits/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_java//java:defs.bzl", "java_binary", "java_library") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") java_library( name = "wpiunits", @@ -7,6 +8,14 @@ java_library( deps = [], ) +wpilib_java_junit5_test( + name = "wpiunits-test", + srcs = glob(["src/test/java/**/*.java"]), + deps = [ + ":wpiunits", + ], +) + java_binary( name = "DevMain-Java", srcs = ["src/dev/java/edu/wpi/first/units/DevMain.java"], diff --git a/wpiutil/BUILD.bazel b/wpiutil/BUILD.bazel index 928fa4e8f3d..646858441c5 100644 --- a/wpiutil/BUILD.bazel +++ b/wpiutil/BUILD.bazel @@ -1,6 +1,8 @@ load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") -load("@rules_java//java:defs.bzl", "java_binary", "java_library") +load("@rules_java//java:defs.bzl", "java_binary") load("@rules_python//python:defs.bzl", "py_binary") +load("//shared/bazel/rules:java_rules.bzl", "wpilib_java_junit5_test") +load("//shared/bazel/rules:jni_rules.bzl", "wpilib_jni_cc_library", "wpilib_jni_java_library") load("//shared/bazel/rules/gen:gen-resources.bzl", "generate_resources") cc_library( @@ -224,9 +226,20 @@ cc_library( }), ) -java_library( +wpilib_jni_cc_library( + name = "wpiutiljni", + srcs = glob(["src/main/native/cpp/jni/**"]), + java_dep = ":wpiutil-java", + visibility = ["//visibility:public"], + deps = [ + ":wpiutil.static", + ], +) + +wpilib_jni_java_library( name = "wpiutil-java", srcs = glob(["src/main/java/**/*.java"]), + native_libs = [":wpiutiljni"], visibility = ["//visibility:public"], deps = [ "@maven//:com_fasterxml_jackson_core_jackson_annotations", @@ -268,6 +281,14 @@ cc_test( ], ) +wpilib_java_junit5_test( + name = "wpiutil-java-test", + srcs = glob(["src/test/java/**/*.java"]), + deps = [ + ":wpiutil-java", + ], +) + cc_binary( name = "DevMain-Cpp", srcs = ["src/dev/native/cpp/main.cpp"],