mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-25 01:41:43 +00:00
Simplify Sendable interface (#1864)
This removes the name and subsystem from individual objects, and instead puts this data into a new singleton class, SendableRegistry. Much of LiveWindow has been refactored into SendableRegistry. In C++, a new CRTP helper class, SendableHelper, has been added to provide move and destruction functionality. Shims for GetName, SetName, GetSubsystem, and SetSubsystem have been added to Command and Subsystem (both old and new), and also to SendableHelper to prevent code breakage. This deprecates SendableBase in preparation for future removal.
This commit is contained in:
@@ -7,63 +7,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
namespace frc {
|
||||
|
||||
class SendableBuilder;
|
||||
|
||||
/**
|
||||
* Interface for Sendable objects.
|
||||
*/
|
||||
class Sendable {
|
||||
public:
|
||||
Sendable() = default;
|
||||
virtual ~Sendable() = default;
|
||||
|
||||
Sendable(const Sendable&) = default;
|
||||
Sendable& operator=(const Sendable&) = default;
|
||||
Sendable(Sendable&&) = default;
|
||||
Sendable& operator=(Sendable&&) = default;
|
||||
|
||||
/**
|
||||
* Gets the name of this Sendable object.
|
||||
*
|
||||
* @return Name
|
||||
*/
|
||||
virtual std::string GetName() const = 0;
|
||||
|
||||
/**
|
||||
* Sets the name of this Sendable object.
|
||||
*
|
||||
* @param name name
|
||||
*/
|
||||
virtual void SetName(const wpi::Twine& name) = 0;
|
||||
|
||||
/**
|
||||
* Sets both the subsystem name and device name of this Sendable object.
|
||||
*
|
||||
* @param subsystem subsystem name
|
||||
* @param name device name
|
||||
*/
|
||||
void SetName(const wpi::Twine& subsystem, const wpi::Twine& name) {
|
||||
SetSubsystem(subsystem);
|
||||
SetName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the subsystem name of this Sendable object.
|
||||
*
|
||||
* @return Subsystem name
|
||||
*/
|
||||
virtual std::string GetSubsystem() const = 0;
|
||||
|
||||
/**
|
||||
* Sets the subsystem name of this Sendable object.
|
||||
*
|
||||
* @param subsystem subsystem name
|
||||
*/
|
||||
virtual void SetSubsystem(const wpi::Twine& subsystem) = 0;
|
||||
|
||||
/**
|
||||
* Initializes this Sendable object.
|
||||
*
|
||||
|
||||
@@ -7,74 +7,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <wpi/deprecated.h>
|
||||
|
||||
#include "frc/smartdashboard/Sendable.h"
|
||||
#include "frc/smartdashboard/SendableHelper.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
class SendableBase : public Sendable {
|
||||
class SendableBase : public Sendable, public SendableHelper<SendableBase> {
|
||||
public:
|
||||
/**
|
||||
* Creates an instance of the sensor base.
|
||||
*
|
||||
* @param addLiveWindow if true, add this Sendable to LiveWindow
|
||||
*/
|
||||
WPI_DEPRECATED("use Sendable and SendableHelper")
|
||||
explicit SendableBase(bool addLiveWindow = true);
|
||||
|
||||
~SendableBase() override;
|
||||
|
||||
SendableBase(const SendableBase&) = default;
|
||||
SendableBase& operator=(const SendableBase&) = default;
|
||||
SendableBase(SendableBase&&);
|
||||
SendableBase& operator=(SendableBase&&);
|
||||
|
||||
using Sendable::SetName;
|
||||
|
||||
std::string GetName() const final;
|
||||
void SetName(const wpi::Twine& name) final;
|
||||
std::string GetSubsystem() const final;
|
||||
void SetSubsystem(const wpi::Twine& subsystem) final;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Add a child component.
|
||||
*
|
||||
* @param child child component
|
||||
*/
|
||||
void AddChild(std::shared_ptr<Sendable> child);
|
||||
|
||||
/**
|
||||
* Add a child component.
|
||||
*
|
||||
* @param child child component
|
||||
*/
|
||||
void AddChild(void* child);
|
||||
|
||||
/**
|
||||
* Sets the name of the sensor with a channel number.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
void SetName(const wpi::Twine& moduleType, int channel);
|
||||
|
||||
/**
|
||||
* Sets the name of the sensor with a module and channel number.
|
||||
*
|
||||
* @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 (usually
|
||||
* PWM)
|
||||
*/
|
||||
void SetName(const wpi::Twine& moduleType, int moduleNumber, int channel);
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
std::string m_subsystem = "Ungrouped";
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
|
||||
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
@@ -14,7 +14,8 @@
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/mutex.h>
|
||||
|
||||
#include "frc/smartdashboard/SendableBase.h"
|
||||
#include "frc/smartdashboard/Sendable.h"
|
||||
#include "frc/smartdashboard/SendableHelper.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
@@ -24,7 +25,8 @@ namespace frc {
|
||||
* It contains static, non-templated variables to avoid their duplication in the
|
||||
* template class.
|
||||
*/
|
||||
class SendableChooserBase : public SendableBase {
|
||||
class SendableChooserBase : public Sendable,
|
||||
public SendableHelper<SendableChooserBase> {
|
||||
public:
|
||||
SendableChooserBase();
|
||||
~SendableChooserBase() override = default;
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/deprecated.h>
|
||||
|
||||
#include "frc/smartdashboard/SendableRegistry.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* A helper class for use with objects that add themselves to SendableRegistry.
|
||||
* It takes care of properly calling Move() and Remove() on move and
|
||||
* destruction. No action is taken if the object is copied.
|
||||
* Use public inheritance with CRTP when using this class.
|
||||
* @tparam CRTP derived class
|
||||
*/
|
||||
template <typename Derived>
|
||||
class SendableHelper {
|
||||
public:
|
||||
SendableHelper(const SendableHelper& rhs) = default;
|
||||
SendableHelper& operator=(const SendableHelper& rhs) = default;
|
||||
|
||||
SendableHelper(SendableHelper&& rhs) {
|
||||
// it is safe to call Move() multiple times with the same rhs
|
||||
SendableRegistry::GetInstance().Move(static_cast<Derived*>(this),
|
||||
static_cast<Derived*>(&rhs));
|
||||
}
|
||||
|
||||
SendableHelper& operator=(SendableHelper&& rhs) {
|
||||
// it is safe to call Move() multiple times with the same rhs
|
||||
SendableRegistry::GetInstance().Move(static_cast<Derived*>(this),
|
||||
static_cast<Derived*>(&rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this Sendable object.
|
||||
*
|
||||
* @return Name
|
||||
*/
|
||||
WPI_DEPRECATED("use SendableRegistry::GetName()")
|
||||
std::string GetName() const {
|
||||
return SendableRegistry::GetInstance().GetName(
|
||||
static_cast<const Derived*>(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of this Sendable object.
|
||||
*
|
||||
* @param name name
|
||||
*/
|
||||
WPI_DEPRECATED("use SendableRegistry::SetName()")
|
||||
void SetName(const wpi::Twine& name) {
|
||||
SendableRegistry::GetInstance().SetName(static_cast<Derived*>(this), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets both the subsystem name and device name of this Sendable object.
|
||||
*
|
||||
* @param subsystem subsystem name
|
||||
* @param name device name
|
||||
*/
|
||||
WPI_DEPRECATED("use SendableRegistry::SetName()")
|
||||
void SetName(const wpi::Twine& subsystem, const wpi::Twine& name) {
|
||||
SendableRegistry::GetInstance().SetName(static_cast<Derived*>(this),
|
||||
subsystem, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the subsystem name of this Sendable object.
|
||||
*
|
||||
* @return Subsystem name
|
||||
*/
|
||||
WPI_DEPRECATED("use SendableRegistry::GetSubsystem()")
|
||||
std::string GetSubsystem() const {
|
||||
return SendableRegistry::GetInstance().GetSubsystem(
|
||||
static_cast<const Derived*>(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the subsystem name of this Sendable object.
|
||||
*
|
||||
* @param subsystem subsystem name
|
||||
*/
|
||||
WPI_DEPRECATED("use SendableRegistry::SetSubsystem()")
|
||||
void SetSubsystem(const wpi::Twine& subsystem) {
|
||||
SendableRegistry::GetInstance().SetSubsystem(static_cast<Derived*>(this),
|
||||
subsystem);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Add a child component.
|
||||
*
|
||||
* @param child child component
|
||||
*/
|
||||
WPI_DEPRECATED("use SendableRegistry::AddChild()")
|
||||
void AddChild(std::shared_ptr<Sendable> child) {
|
||||
SendableRegistry::GetInstance().AddChild(static_cast<Derived*>(this),
|
||||
child.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child component.
|
||||
*
|
||||
* @param child child component
|
||||
*/
|
||||
WPI_DEPRECATED("use SendableRegistry::AddChild()")
|
||||
void AddChild(void* child) {
|
||||
SendableRegistry::GetInstance().AddChild(static_cast<Derived*>(this),
|
||||
child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the sensor with a channel number.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
WPI_DEPRECATED("use SendableRegistry::SetName()")
|
||||
void SetName(const wpi::Twine& moduleType, int channel) {
|
||||
SendableRegistry::GetInstance().SetName(static_cast<Derived*>(this),
|
||||
moduleType, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the sensor with a module and channel number.
|
||||
*
|
||||
* @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 (usually
|
||||
* PWM)
|
||||
*/
|
||||
WPI_DEPRECATED("use SendableRegistry::SetName()")
|
||||
void SetName(const wpi::Twine& moduleType, int moduleNumber, int channel) {
|
||||
SendableRegistry::GetInstance().SetName(static_cast<Derived*>(this),
|
||||
moduleType, moduleNumber, channel);
|
||||
}
|
||||
|
||||
protected:
|
||||
SendableHelper() = default;
|
||||
|
||||
~SendableHelper() {
|
||||
// it is safe to call Remove() multiple times with the same object
|
||||
SendableRegistry::GetInstance().Remove(static_cast<Derived*>(this));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -0,0 +1,277 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
namespace frc {
|
||||
|
||||
class Sendable;
|
||||
|
||||
/**
|
||||
* The SendableRegistry class is the public interface for registering sensors
|
||||
* and actuators for use on dashboards and LiveWindow.
|
||||
*/
|
||||
class SendableRegistry {
|
||||
public:
|
||||
SendableRegistry(const SendableRegistry&) = delete;
|
||||
SendableRegistry& operator=(const SendableRegistry&) = delete;
|
||||
|
||||
/**
|
||||
* Gets an instance of the SendableRegistry class.
|
||||
*
|
||||
* This is a singleton to guarantee that there is only a single instance
|
||||
* regardless of how many times GetInstance is called.
|
||||
*/
|
||||
static SendableRegistry& GetInstance();
|
||||
|
||||
/**
|
||||
* Adds an object to the registry.
|
||||
*
|
||||
* @param sendable object to add
|
||||
* @param name component name
|
||||
*/
|
||||
void Add(Sendable* sendable, const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Adds an object to the registry.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
void Add(Sendable* sendable, const wpi::Twine& moduleType, int channel);
|
||||
|
||||
/**
|
||||
* Adds an object to the registry.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
void Add(Sendable* sendable, const wpi::Twine& moduleType, int moduleNumber,
|
||||
int channel);
|
||||
|
||||
/**
|
||||
* Adds an object to the registry.
|
||||
*
|
||||
* @param sendable object to add
|
||||
* @param subsystem subsystem name
|
||||
* @param name component name
|
||||
*/
|
||||
void Add(Sendable* sendable, const wpi::Twine& subsystem,
|
||||
const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Adds an object to the registry and LiveWindow.
|
||||
*
|
||||
* @param sendable object to add
|
||||
* @param name component name
|
||||
*/
|
||||
void AddLW(Sendable* sendable, const wpi::Twine& 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
|
||||
*/
|
||||
void AddLW(Sendable* sendable, const wpi::Twine& 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
|
||||
*/
|
||||
void AddLW(Sendable* sendable, const wpi::Twine& 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
|
||||
*/
|
||||
void AddLW(Sendable* sendable, const wpi::Twine& subsystem,
|
||||
const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Adds a child object to an object. Adds the child object to the registry
|
||||
* if it's not already present.
|
||||
*
|
||||
* @param parent parent object
|
||||
* @param child child object
|
||||
*/
|
||||
void AddChild(Sendable* parent, void* child);
|
||||
|
||||
/**
|
||||
* Removes an object from the registry.
|
||||
*
|
||||
* @param sendable object to remove
|
||||
* @return true if the object was removed; false if it was not present
|
||||
*/
|
||||
bool Remove(Sendable* sendable);
|
||||
|
||||
/**
|
||||
* Moves an object in the registry (for use in move constructors/assignments).
|
||||
*
|
||||
* @param to new object
|
||||
* @param from old object
|
||||
*/
|
||||
void Move(Sendable* to, Sendable* from);
|
||||
|
||||
/**
|
||||
* Determines if an object is in the registry.
|
||||
*
|
||||
* @param sendable object to check
|
||||
* @return True if in registry, false if not.
|
||||
*/
|
||||
bool Contains(const Sendable* sendable) const;
|
||||
|
||||
/**
|
||||
* Gets the name of an object.
|
||||
*
|
||||
* @param sendable object
|
||||
* @return Name (empty if object is not in registry)
|
||||
*/
|
||||
std::string GetName(const Sendable* sendable) const;
|
||||
|
||||
/**
|
||||
* Sets the name of an object.
|
||||
*
|
||||
* @param sendable object
|
||||
* @param name name
|
||||
*/
|
||||
void SetName(Sendable* sendable, const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Sets the name of an object with a channel number.
|
||||
*
|
||||
* @param sendable object
|
||||
* @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
|
||||
*/
|
||||
void SetName(Sendable* sendable, const wpi::Twine& moduleType, int channel);
|
||||
|
||||
/**
|
||||
* Sets the name of an object with a module and channel number.
|
||||
*
|
||||
* @param sendable object
|
||||
* @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
|
||||
*/
|
||||
void SetName(Sendable* sendable, const wpi::Twine& moduleType,
|
||||
int moduleNumber, int channel);
|
||||
|
||||
/**
|
||||
* Sets both the subsystem name and device name of an object.
|
||||
*
|
||||
* @param sendable object
|
||||
* @param subsystem subsystem name
|
||||
* @param name device name
|
||||
*/
|
||||
void SetName(Sendable* sendable, const wpi::Twine& subsystem,
|
||||
const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Gets the subsystem name of an object.
|
||||
*
|
||||
* @param sendable object
|
||||
* @return Subsystem name (empty if object is not in registry)
|
||||
*/
|
||||
std::string GetSubsystem(const Sendable* sendable) const;
|
||||
|
||||
/**
|
||||
* Sets the subsystem name of an object.
|
||||
*
|
||||
* @param sendable object
|
||||
* @param subsystem subsystem name
|
||||
*/
|
||||
void SetSubsystem(Sendable* sendable, const wpi::Twine& subsystem);
|
||||
|
||||
/**
|
||||
* Gets a unique handle for setting/getting data with SetData() and GetData().
|
||||
*
|
||||
* @return Handle
|
||||
*/
|
||||
int GetDataHandle();
|
||||
|
||||
/**
|
||||
* Associates arbitrary data with an object in the registry.
|
||||
*
|
||||
* @param sendable object
|
||||
* @param handle data handle returned by GetDataHandle()
|
||||
* @param data data to set
|
||||
* @return Previous data (may be null)
|
||||
*/
|
||||
std::shared_ptr<void> SetData(Sendable* sendable, int handle,
|
||||
std::shared_ptr<void> data);
|
||||
|
||||
/**
|
||||
* Gets arbitrary data associated with an object in the registry.
|
||||
*
|
||||
* @param sendable object
|
||||
* @param handle data handle returned by GetDataHandle()
|
||||
* @return data (may be null if none associated)
|
||||
*/
|
||||
std::shared_ptr<void> GetData(Sendable* sendable, int handle);
|
||||
|
||||
/**
|
||||
* Enables LiveWindow for an object.
|
||||
*
|
||||
* @param sendable object
|
||||
*/
|
||||
void EnableLiveWindow(Sendable* sendable);
|
||||
|
||||
/**
|
||||
* Disables LiveWindow for an object.
|
||||
*
|
||||
* @param sendable object
|
||||
*/
|
||||
void DisableLiveWindow(Sendable* sendable);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void ForeachLiveWindow(
|
||||
int dataHandle,
|
||||
wpi::function_ref<void(Sendable* sendable, wpi::StringRef name,
|
||||
wpi::StringRef subsystem, Sendable* parent,
|
||||
std::shared_ptr<void>& data)>
|
||||
callback) const;
|
||||
|
||||
private:
|
||||
SendableRegistry();
|
||||
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -15,13 +15,14 @@
|
||||
|
||||
#include "frc/ErrorBase.h"
|
||||
#include "frc/smartdashboard/ListenerExecutor.h"
|
||||
#include "frc/smartdashboard/SendableBase.h"
|
||||
#include "frc/smartdashboard/Sendable.h"
|
||||
#include "frc/smartdashboard/SendableHelper.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
class Sendable;
|
||||
|
||||
class SmartDashboard : public ErrorBase, public SendableBase {
|
||||
class SmartDashboard : public ErrorBase,
|
||||
public Sendable,
|
||||
public SendableHelper<SmartDashboard> {
|
||||
public:
|
||||
static void init();
|
||||
|
||||
@@ -101,6 +102,9 @@ class SmartDashboard : public ErrorBase, public SendableBase {
|
||||
* The value can be retrieved by calling the get method with a key that is
|
||||
* equal to the original key.
|
||||
*
|
||||
* In order for the value to appear in the dashboard, it must be registered
|
||||
* with SendableRegistry. WPILib components do this automatically.
|
||||
*
|
||||
* @param keyName the key
|
||||
* @param value the value
|
||||
*/
|
||||
@@ -113,6 +117,9 @@ class SmartDashboard : public ErrorBase, public SendableBase {
|
||||
* The value can be retrieved by calling the get method with a key that is
|
||||
* equal to the original key.
|
||||
*
|
||||
* In order for the value to appear in the dashboard, it must be registered
|
||||
* with SendableRegistry. WPILib components do this automatically.
|
||||
*
|
||||
* @param value the value
|
||||
*/
|
||||
static void PutData(Sendable* value);
|
||||
|
||||
Reference in New Issue
Block a user