mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-23 01:21:42 +00:00
[ntcore] NetworkTables 4 (#3217)
This commit is contained in:
@@ -873,8 +873,6 @@ int ADIS16448_IMU::GetPort() const {
|
||||
**/
|
||||
void ADIS16448_IMU::InitSendable(nt::NTSendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("ADIS16448 IMU");
|
||||
auto yaw_angle = builder.GetEntry("Yaw Angle").GetHandle();
|
||||
builder.SetUpdateTable([=]() {
|
||||
nt::NetworkTableEntry(yaw_angle).SetDouble(GetAngle().value());
|
||||
});
|
||||
builder.AddDoubleProperty(
|
||||
"Yaw Angle", [=] { return GetAngle().value(); }, nullptr);
|
||||
}
|
||||
|
||||
@@ -808,8 +808,6 @@ int ADIS16470_IMU::GetPort() const {
|
||||
**/
|
||||
void ADIS16470_IMU::InitSendable(nt::NTSendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("ADIS16470 IMU");
|
||||
auto yaw_angle = builder.GetEntry("Yaw Angle").GetHandle();
|
||||
builder.SetUpdateTable([=]() {
|
||||
nt::NetworkTableEntry(yaw_angle).SetDouble(GetAngle().value());
|
||||
});
|
||||
builder.AddDoubleProperty(
|
||||
"Yaw Angle", [=] { return GetAngle().value(); }, nullptr);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "frc/ADXL345_I2C.h"
|
||||
|
||||
#include <hal/FRCUsageReporting.h>
|
||||
#include <networktables/DoubleTopic.h>
|
||||
#include <networktables/NTSendableBuilder.h>
|
||||
#include <wpi/sendable/SendableRegistry.h>
|
||||
|
||||
@@ -93,13 +94,13 @@ ADXL345_I2C::AllAxes ADXL345_I2C::GetAccelerations() {
|
||||
|
||||
void ADXL345_I2C::InitSendable(nt::NTSendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("3AxisAccelerometer");
|
||||
auto x = builder.GetEntry("X").GetHandle();
|
||||
auto y = builder.GetEntry("Y").GetHandle();
|
||||
auto z = builder.GetEntry("Z").GetHandle();
|
||||
builder.SetUpdateTable([=] {
|
||||
auto data = GetAccelerations();
|
||||
nt::NetworkTableEntry(x).SetDouble(data.XAxis);
|
||||
nt::NetworkTableEntry(y).SetDouble(data.YAxis);
|
||||
nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
|
||||
});
|
||||
builder.SetUpdateTable(
|
||||
[this, x = nt::DoubleTopic{builder.GetTopic("X")}.Publish(),
|
||||
y = nt::DoubleTopic{builder.GetTopic("Y")}.Publish(),
|
||||
z = nt::DoubleTopic{builder.GetTopic("Z")}.Publish()]() mutable {
|
||||
auto data = GetAccelerations();
|
||||
x.Set(data.XAxis);
|
||||
y.Set(data.YAxis);
|
||||
z.Set(data.ZAxis);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "frc/ADXL345_SPI.h"
|
||||
|
||||
#include <hal/FRCUsageReporting.h>
|
||||
#include <networktables/DoubleTopic.h>
|
||||
#include <networktables/NTSendableBuilder.h>
|
||||
#include <wpi/sendable/SendableRegistry.h>
|
||||
|
||||
@@ -118,13 +119,13 @@ ADXL345_SPI::AllAxes ADXL345_SPI::GetAccelerations() {
|
||||
|
||||
void ADXL345_SPI::InitSendable(nt::NTSendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("3AxisAccelerometer");
|
||||
auto x = builder.GetEntry("X").GetHandle();
|
||||
auto y = builder.GetEntry("Y").GetHandle();
|
||||
auto z = builder.GetEntry("Z").GetHandle();
|
||||
builder.SetUpdateTable([=] {
|
||||
auto data = GetAccelerations();
|
||||
nt::NetworkTableEntry(x).SetDouble(data.XAxis);
|
||||
nt::NetworkTableEntry(y).SetDouble(data.YAxis);
|
||||
nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
|
||||
});
|
||||
builder.SetUpdateTable(
|
||||
[this, x = nt::DoubleTopic{builder.GetTopic("X")}.Publish(),
|
||||
y = nt::DoubleTopic{builder.GetTopic("Y")}.Publish(),
|
||||
z = nt::DoubleTopic{builder.GetTopic("Z")}.Publish()]() mutable {
|
||||
auto data = GetAccelerations();
|
||||
x.Set(data.XAxis);
|
||||
y.Set(data.YAxis);
|
||||
z.Set(data.ZAxis);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "frc/ADXL362.h"
|
||||
|
||||
#include <hal/FRCUsageReporting.h>
|
||||
#include <networktables/DoubleTopic.h>
|
||||
#include <networktables/NTSendableBuilder.h>
|
||||
#include <wpi/sendable/SendableRegistry.h>
|
||||
|
||||
@@ -182,13 +183,13 @@ ADXL362::AllAxes ADXL362::GetAccelerations() {
|
||||
|
||||
void ADXL362::InitSendable(nt::NTSendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("3AxisAccelerometer");
|
||||
auto x = builder.GetEntry("X").GetHandle();
|
||||
auto y = builder.GetEntry("Y").GetHandle();
|
||||
auto z = builder.GetEntry("Z").GetHandle();
|
||||
builder.SetUpdateTable([=] {
|
||||
auto data = GetAccelerations();
|
||||
nt::NetworkTableEntry(x).SetDouble(data.XAxis);
|
||||
nt::NetworkTableEntry(y).SetDouble(data.YAxis);
|
||||
nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
|
||||
});
|
||||
builder.SetUpdateTable(
|
||||
[this, x = nt::DoubleTopic{builder.GetTopic("X")}.Publish(),
|
||||
y = nt::DoubleTopic{builder.GetTopic("Y")}.Publish(),
|
||||
z = nt::DoubleTopic{builder.GetTopic("Z")}.Publish()]() mutable {
|
||||
auto data = GetAccelerations();
|
||||
x.Set(data.XAxis);
|
||||
y.Set(data.YAxis);
|
||||
z.Set(data.ZAxis);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
#include <hal/DriverStationTypes.h>
|
||||
#include <hal/HALBase.h>
|
||||
#include <hal/Power.h>
|
||||
#include <networktables/BooleanTopic.h>
|
||||
#include <networktables/IntegerTopic.h>
|
||||
#include <networktables/NetworkTable.h>
|
||||
#include <networktables/NetworkTableEntry.h>
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
#include <networktables/StringTopic.h>
|
||||
#include <wpi/DataLog.h>
|
||||
#include <wpi/condition_variable.h>
|
||||
#include <wpi/mutex.h>
|
||||
@@ -36,56 +38,42 @@ using namespace frc;
|
||||
namespace {
|
||||
// A simple class which caches the previous value written to an NT entry
|
||||
// Used to prevent redundant, repeated writes of the same value
|
||||
template <class T>
|
||||
template <typename Topic>
|
||||
class MatchDataSenderEntry {
|
||||
public:
|
||||
MatchDataSenderEntry(const std::shared_ptr<nt::NetworkTable>& table,
|
||||
std::string_view key, const T& initialVal) {
|
||||
static_assert(std::is_same_v<T, bool> || std::is_same_v<T, double> ||
|
||||
std::is_same_v<T, std::string>,
|
||||
"Invalid type for MatchDataSenderEntry - must be "
|
||||
"to bool, double or std::string");
|
||||
|
||||
ntEntry = table->GetEntry(key);
|
||||
if constexpr (std::is_same_v<T, bool>) {
|
||||
ntEntry.ForceSetBoolean(initialVal);
|
||||
} else if constexpr (std::is_same_v<T, double>) {
|
||||
ntEntry.ForceSetDouble(initialVal);
|
||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||
ntEntry.ForceSetString(initialVal);
|
||||
}
|
||||
prevVal = initialVal;
|
||||
std::string_view key,
|
||||
typename Topic::ParamType initialVal)
|
||||
: publisher{Topic{table->GetTopic(key)}.Publish()}, prevVal{initialVal} {
|
||||
publisher.Set(initialVal);
|
||||
}
|
||||
|
||||
void Set(const T& val) {
|
||||
void Set(typename Topic::ParamType val) {
|
||||
if (val != prevVal) {
|
||||
SetValue(val);
|
||||
publisher.Set(val);
|
||||
prevVal = val;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nt::NetworkTableEntry ntEntry;
|
||||
T prevVal;
|
||||
|
||||
void SetValue(bool val) { ntEntry.SetBoolean(val); }
|
||||
void SetValue(double val) { ntEntry.SetDouble(val); }
|
||||
void SetValue(std::string_view val) { ntEntry.SetString(val); }
|
||||
typename Topic::PublisherType publisher;
|
||||
typename Topic::ValueType prevVal;
|
||||
};
|
||||
|
||||
struct MatchDataSender {
|
||||
std::shared_ptr<nt::NetworkTable> table =
|
||||
nt::NetworkTableInstance::GetDefault().GetTable("FMSInfo");
|
||||
MatchDataSenderEntry<std::string> typeMetaData{table, ".type", "FMSInfo"};
|
||||
MatchDataSenderEntry<std::string> gameSpecificMessage{
|
||||
MatchDataSenderEntry<nt::StringTopic> typeMetaData{table, ".type", "FMSInfo"};
|
||||
MatchDataSenderEntry<nt::StringTopic> gameSpecificMessage{
|
||||
table, "GameSpecificMessage", ""};
|
||||
MatchDataSenderEntry<std::string> eventName{table, "EventName", ""};
|
||||
MatchDataSenderEntry<double> matchNumber{table, "MatchNumber", 0.0};
|
||||
MatchDataSenderEntry<double> replayNumber{table, "ReplayNumber", 0.0};
|
||||
MatchDataSenderEntry<double> matchType{table, "MatchType", 0.0};
|
||||
MatchDataSenderEntry<bool> alliance{table, "IsRedAlliance", true};
|
||||
MatchDataSenderEntry<double> station{table, "StationNumber", 1.0};
|
||||
MatchDataSenderEntry<double> controlWord{table, "FMSControlData", 0.0};
|
||||
MatchDataSenderEntry<nt::StringTopic> eventName{table, "EventName", ""};
|
||||
MatchDataSenderEntry<nt::IntegerTopic> matchNumber{table, "MatchNumber", 0};
|
||||
MatchDataSenderEntry<nt::IntegerTopic> replayNumber{table, "ReplayNumber", 0};
|
||||
MatchDataSenderEntry<nt::IntegerTopic> matchType{table, "MatchType", 0};
|
||||
MatchDataSenderEntry<nt::BooleanTopic> alliance{table, "IsRedAlliance", true};
|
||||
MatchDataSenderEntry<nt::IntegerTopic> station{table, "StationNumber", 1};
|
||||
MatchDataSenderEntry<nt::IntegerTopic> controlWord{table, "FMSControlData",
|
||||
0};
|
||||
};
|
||||
|
||||
class JoystickLogSender {
|
||||
|
||||
@@ -187,7 +187,7 @@ void IterativeRobotBase::LoopFunc() {
|
||||
|
||||
// Flush NetworkTables
|
||||
if (m_ntFlushEnabled) {
|
||||
nt::NetworkTableInstance::GetDefault().Flush();
|
||||
nt::NetworkTableInstance::GetDefault().FlushLocal();
|
||||
}
|
||||
|
||||
// Warn on loop time overruns
|
||||
|
||||
@@ -6,9 +6,13 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <hal/FRCUsageReporting.h>
|
||||
#include <networktables/MultiSubscriber.h>
|
||||
#include <networktables/NetworkTable.h>
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
#include <networktables/StringTopic.h>
|
||||
#include <networktables/TopicListener.h>
|
||||
|
||||
using namespace frc;
|
||||
|
||||
@@ -21,7 +25,10 @@ struct Instance {
|
||||
|
||||
std::shared_ptr<nt::NetworkTable> table{
|
||||
nt::NetworkTableInstance::GetDefault().GetTable(kTableName)};
|
||||
NT_EntryListener listener;
|
||||
nt::StringPublisher typePublisher{table->GetStringTopic(".type").Publish()};
|
||||
nt::MultiSubscriber tableSubscriber{nt::NetworkTableInstance::GetDefault(),
|
||||
{{kTableName}}};
|
||||
nt::TopicListener listener;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -44,28 +51,27 @@ std::vector<std::string> Preferences::GetKeys() {
|
||||
|
||||
std::string Preferences::GetString(std::string_view key,
|
||||
std::string_view defaultValue) {
|
||||
return ::GetInstance().table->GetString(key, defaultValue);
|
||||
return ::GetInstance().table->GetEntry(key).GetString(defaultValue);
|
||||
}
|
||||
|
||||
int Preferences::GetInt(std::string_view key, int defaultValue) {
|
||||
return static_cast<int>(::GetInstance().table->GetNumber(key, defaultValue));
|
||||
return ::GetInstance().table->GetEntry(key).GetInteger(defaultValue);
|
||||
}
|
||||
|
||||
double Preferences::GetDouble(std::string_view key, double defaultValue) {
|
||||
return ::GetInstance().table->GetNumber(key, defaultValue);
|
||||
return ::GetInstance().table->GetEntry(key).GetDouble(defaultValue);
|
||||
}
|
||||
|
||||
float Preferences::GetFloat(std::string_view key, float defaultValue) {
|
||||
return ::GetInstance().table->GetNumber(key, defaultValue);
|
||||
return ::GetInstance().table->GetEntry(key).GetFloat(defaultValue);
|
||||
}
|
||||
|
||||
bool Preferences::GetBoolean(std::string_view key, bool defaultValue) {
|
||||
return ::GetInstance().table->GetBoolean(key, defaultValue);
|
||||
return ::GetInstance().table->GetEntry(key).GetBoolean(defaultValue);
|
||||
}
|
||||
|
||||
int64_t Preferences::GetLong(std::string_view key, int64_t defaultValue) {
|
||||
return static_cast<int64_t>(
|
||||
::GetInstance().table->GetNumber(key, defaultValue));
|
||||
return ::GetInstance().table->GetEntry(key).GetInteger(defaultValue);
|
||||
}
|
||||
|
||||
void Preferences::SetString(std::string_view key, std::string_view value) {
|
||||
@@ -82,13 +88,13 @@ void Preferences::InitString(std::string_view key, std::string_view value) {
|
||||
|
||||
void Preferences::SetInt(std::string_view key, int value) {
|
||||
auto entry = ::GetInstance().table->GetEntry(key);
|
||||
entry.SetDouble(value);
|
||||
entry.SetInteger(value);
|
||||
entry.SetPersistent();
|
||||
}
|
||||
|
||||
void Preferences::InitInt(std::string_view key, int value) {
|
||||
auto entry = ::GetInstance().table->GetEntry(key);
|
||||
entry.SetDefaultDouble(value);
|
||||
entry.SetDefaultInteger(value);
|
||||
entry.SetPersistent();
|
||||
}
|
||||
|
||||
@@ -106,13 +112,13 @@ void Preferences::InitDouble(std::string_view key, double value) {
|
||||
|
||||
void Preferences::SetFloat(std::string_view key, float value) {
|
||||
auto entry = ::GetInstance().table->GetEntry(key);
|
||||
entry.SetDouble(value);
|
||||
entry.SetFloat(value);
|
||||
entry.SetPersistent();
|
||||
}
|
||||
|
||||
void Preferences::InitFloat(std::string_view key, float value) {
|
||||
auto entry = ::GetInstance().table->GetEntry(key);
|
||||
entry.SetDefaultDouble(value);
|
||||
entry.SetDefaultFloat(value);
|
||||
entry.SetPersistent();
|
||||
}
|
||||
|
||||
@@ -130,13 +136,13 @@ void Preferences::InitBoolean(std::string_view key, bool value) {
|
||||
|
||||
void Preferences::SetLong(std::string_view key, int64_t value) {
|
||||
auto entry = ::GetInstance().table->GetEntry(key);
|
||||
entry.SetDouble(value);
|
||||
entry.SetInteger(value);
|
||||
entry.SetPersistent();
|
||||
}
|
||||
|
||||
void Preferences::InitLong(std::string_view key, int64_t value) {
|
||||
auto entry = ::GetInstance().table->GetEntry(key);
|
||||
entry.SetDefaultDouble(value);
|
||||
entry.SetDefaultInteger(value);
|
||||
entry.SetPersistent();
|
||||
}
|
||||
|
||||
@@ -145,7 +151,9 @@ bool Preferences::ContainsKey(std::string_view key) {
|
||||
}
|
||||
|
||||
void Preferences::Remove(std::string_view key) {
|
||||
::GetInstance().table->Delete(key);
|
||||
auto entry = ::GetInstance().table->GetEntry(key);
|
||||
entry.ClearPersistent();
|
||||
entry.Unpublish();
|
||||
}
|
||||
|
||||
void Preferences::RemoveAll() {
|
||||
@@ -157,11 +165,13 @@ void Preferences::RemoveAll() {
|
||||
}
|
||||
|
||||
Instance::Instance() {
|
||||
table->GetEntry(".type").SetString("RobotPreferences");
|
||||
listener = table->AddEntryListener(
|
||||
[=](nt::NetworkTable* table, std::string_view name,
|
||||
nt::NetworkTableEntry entry, std::shared_ptr<nt::Value> value,
|
||||
int flags) { entry.SetPersistent(); },
|
||||
NT_NOTIFY_NEW | NT_NOTIFY_IMMEDIATE);
|
||||
typePublisher.Set("RobotPreferences");
|
||||
listener = nt::TopicListener{
|
||||
table->GetInstance(),
|
||||
{{std::string_view{fmt::format("{}/", table->GetPath())}}},
|
||||
NT_TOPIC_NOTIFY_IMMEDIATE | NT_TOPIC_NOTIFY_PUBLISH,
|
||||
[](const nt::TopicNotification& event) {
|
||||
nt::SetTopicPersistent(event.info.topic, true);
|
||||
}};
|
||||
HAL_Report(HALUsageReporting::kResourceType_Preferences, 0);
|
||||
}
|
||||
|
||||
40
wpilibc/src/main/native/cpp/event/NetworkBooleanEvent.cpp
Normal file
40
wpilibc/src/main/native/cpp/event/NetworkBooleanEvent.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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/event/NetworkBooleanEvent.h"
|
||||
|
||||
#include <networktables/BooleanTopic.h>
|
||||
#include <networktables/NetworkTable.h>
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
|
||||
using namespace frc;
|
||||
|
||||
NetworkBooleanEvent::NetworkBooleanEvent(EventLoop* loop,
|
||||
nt::BooleanTopic topic)
|
||||
: NetworkBooleanEvent{loop, topic.Subscribe(false)} {}
|
||||
|
||||
NetworkBooleanEvent::NetworkBooleanEvent(EventLoop* loop,
|
||||
nt::BooleanSubscriber sub)
|
||||
: BooleanEvent{
|
||||
loop,
|
||||
[sub = std::make_shared<nt::BooleanSubscriber>(std::move(sub))] {
|
||||
return sub->GetTopic().GetInstance().IsConnected() && sub->Get();
|
||||
}} {}
|
||||
|
||||
NetworkBooleanEvent::NetworkBooleanEvent(
|
||||
EventLoop* loop, std::shared_ptr<nt::NetworkTable> table,
|
||||
std::string_view topicName)
|
||||
: NetworkBooleanEvent{loop, table->GetBooleanTopic(topicName)} {}
|
||||
|
||||
NetworkBooleanEvent::NetworkBooleanEvent(EventLoop* loop,
|
||||
std::string_view tableName,
|
||||
std::string_view topicName)
|
||||
: NetworkBooleanEvent{loop, nt::NetworkTableInstance::GetDefault(),
|
||||
tableName, topicName} {}
|
||||
|
||||
NetworkBooleanEvent::NetworkBooleanEvent(EventLoop* loop,
|
||||
nt::NetworkTableInstance inst,
|
||||
std::string_view tableName,
|
||||
std::string_view topicName)
|
||||
: NetworkBooleanEvent{loop, inst.GetTable(tableName), topicName} {}
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
#include "frc/livewindow/LiveWindow.h"
|
||||
|
||||
#include <networktables/BooleanTopic.h>
|
||||
#include <networktables/NetworkTable.h>
|
||||
#include <networktables/NetworkTableEntry.h>
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
#include <networktables/StringTopic.h>
|
||||
#include <wpi/mutex.h>
|
||||
#include <wpi/sendable/Sendable.h>
|
||||
#include <wpi/sendable/SendableRegistry.h>
|
||||
@@ -19,12 +20,15 @@ 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<SendableBuilderImpl>(); });
|
||||
enabledPub.Set(false);
|
||||
}
|
||||
|
||||
wpi::mutex mutex;
|
||||
@@ -35,7 +39,8 @@ struct Instance {
|
||||
nt::NetworkTableInstance::GetDefault().GetTable("LiveWindow");
|
||||
std::shared_ptr<nt::NetworkTable> statusTable =
|
||||
liveWindowTable->GetSubTable(".status");
|
||||
nt::NetworkTableEntry enabledEntry = statusTable->GetEntry("LW Enabled");
|
||||
nt::BooleanPublisher enabledPub =
|
||||
statusTable->GetBooleanTopic("LW Enabled").Publish();
|
||||
|
||||
bool startLiveWindow = false;
|
||||
bool liveWindowEnabled = false;
|
||||
@@ -139,7 +144,7 @@ void LiveWindow::SetEnabled(bool enabled) {
|
||||
inst.disabled();
|
||||
}
|
||||
}
|
||||
inst.enabledEntry.SetBoolean(enabled);
|
||||
inst.enabledPub.Set(enabled);
|
||||
}
|
||||
|
||||
void LiveWindow::UpdateValues() {
|
||||
@@ -186,10 +191,12 @@ void LiveWindow::UpdateValuesUnsafe() {
|
||||
} else {
|
||||
table = ssTable->GetSubTable(cbdata.name);
|
||||
}
|
||||
table->GetEntry(".name").SetString(cbdata.name);
|
||||
comp.namePub = nt::StringTopic{table->GetTopic(".name")}.Publish();
|
||||
comp.namePub.Set(cbdata.name);
|
||||
static_cast<SendableBuilderImpl&>(cbdata.builder).SetTable(table);
|
||||
cbdata.sendable->InitSendable(cbdata.builder);
|
||||
ssTable->GetEntry(".type").SetString("LW Subsystem");
|
||||
comp.typePub = nt::StringTopic{ssTable->GetTopic(".type")}.Publish();
|
||||
comp.typePub.Set("LW Subsystem");
|
||||
|
||||
comp.firstTime = false;
|
||||
}
|
||||
|
||||
@@ -9,29 +9,30 @@
|
||||
using namespace frc;
|
||||
using namespace frc::detail;
|
||||
|
||||
RecordingController::RecordingController(nt::NetworkTableInstance ntInstance)
|
||||
: m_recordingControlEntry(), m_recordingFileNameFormatEntry() {
|
||||
RecordingController::RecordingController(nt::NetworkTableInstance ntInstance) {
|
||||
m_recordingControlEntry =
|
||||
ntInstance.GetEntry("/Shuffleboard/.recording/RecordData");
|
||||
ntInstance.GetBooleanTopic("/Shuffleboard/.recording/RecordData")
|
||||
.Publish();
|
||||
m_recordingFileNameFormatEntry =
|
||||
ntInstance.GetEntry("/Shuffleboard/.recording/FileNameFormat");
|
||||
ntInstance.GetStringTopic("/Shuffleboard/.recording/FileNameFormat")
|
||||
.Publish();
|
||||
m_eventsTable = ntInstance.GetTable("/Shuffleboard/.recording/events");
|
||||
}
|
||||
|
||||
void RecordingController::StartRecording() {
|
||||
m_recordingControlEntry.SetBoolean(true);
|
||||
m_recordingControlEntry.Set(true);
|
||||
}
|
||||
|
||||
void RecordingController::StopRecording() {
|
||||
m_recordingControlEntry.SetBoolean(false);
|
||||
m_recordingControlEntry.Set(false);
|
||||
}
|
||||
|
||||
void RecordingController::SetRecordingFileNameFormat(std::string_view format) {
|
||||
m_recordingFileNameFormatEntry.SetString(format);
|
||||
m_recordingFileNameFormatEntry.Set(format);
|
||||
}
|
||||
|
||||
void RecordingController::ClearRecordingFileNameFormat() {
|
||||
m_recordingFileNameFormatEntry.Delete();
|
||||
m_recordingFileNameFormatEntry.Set("");
|
||||
}
|
||||
|
||||
void RecordingController::AddEventMarker(
|
||||
@@ -43,6 +44,6 @@ void RecordingController::AddEventMarker(
|
||||
return;
|
||||
}
|
||||
m_eventsTable->GetSubTable(name)->GetEntry("Info").SetStringArray(
|
||||
{std::string{description},
|
||||
std::string{ShuffleboardEventImportanceName(importance)}});
|
||||
{{std::string{description},
|
||||
std::string{ShuffleboardEventImportanceName(importance)}}});
|
||||
}
|
||||
|
||||
@@ -22,27 +22,21 @@ void ShuffleboardComponentBase::BuildMetadata(
|
||||
return;
|
||||
}
|
||||
// Component type
|
||||
if (GetType() == "") {
|
||||
metaTable->GetEntry("PreferredComponent").Delete();
|
||||
} else {
|
||||
metaTable->GetEntry("PreferredComponent").ForceSetString(GetType());
|
||||
if (!GetType().empty()) {
|
||||
metaTable->GetEntry("PreferredComponent").SetString(GetType());
|
||||
}
|
||||
|
||||
// Tile size
|
||||
if (m_width <= 0 || m_height <= 0) {
|
||||
metaTable->GetEntry("Size").Delete();
|
||||
} else {
|
||||
if (m_width > 0 && m_height > 0) {
|
||||
metaTable->GetEntry("Size").SetDoubleArray(
|
||||
{static_cast<double>(m_width), static_cast<double>(m_height)});
|
||||
{{static_cast<double>(m_width), static_cast<double>(m_height)}});
|
||||
}
|
||||
|
||||
// Tile position
|
||||
if (m_column < 0 || m_row < 0) {
|
||||
metaTable->GetEntry("Position").Delete();
|
||||
} else {
|
||||
if (m_column >= 0 && m_row >= 0) {
|
||||
metaTable->GetEntry("Position")
|
||||
.SetDoubleArray(
|
||||
{static_cast<double>(m_column), static_cast<double>(m_row)});
|
||||
{{static_cast<double>(m_column), static_cast<double>(m_row)}});
|
||||
}
|
||||
|
||||
// Custom properties
|
||||
@@ -63,7 +57,7 @@ const std::string& ShuffleboardComponentBase::GetType() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
const wpi::StringMap<std::shared_ptr<nt::Value>>&
|
||||
ShuffleboardComponentBase::GetProperties() const {
|
||||
const wpi::StringMap<nt::Value>& ShuffleboardComponentBase::GetProperties()
|
||||
const {
|
||||
return m_properties;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "frc/shuffleboard/ShuffleboardContainer.h"
|
||||
|
||||
#include <ntcore_cpp.h>
|
||||
#include <wpi/sendable/SendableRegistry.h>
|
||||
|
||||
#include "frc/Errors.h"
|
||||
@@ -74,14 +75,15 @@ ComplexWidget& ShuffleboardContainer::Add(wpi::Sendable& sendable) {
|
||||
return Add(name, sendable);
|
||||
}
|
||||
|
||||
SimpleWidget& ShuffleboardContainer::Add(
|
||||
std::string_view title, std::shared_ptr<nt::Value> defaultValue) {
|
||||
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
|
||||
const nt::Value& defaultValue) {
|
||||
CheckTitle(title);
|
||||
|
||||
auto widget = std::make_unique<SimpleWidget>(*this, title);
|
||||
auto ptr = widget.get();
|
||||
m_components.emplace_back(std::move(widget));
|
||||
ptr->GetEntry().SetDefaultValue(defaultValue);
|
||||
ptr->GetEntry(nt::GetStringFromType(defaultValue.type()))
|
||||
.SetDefault(defaultValue);
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
@@ -95,9 +97,14 @@ SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
|
||||
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::MakeDouble(defaultValue));
|
||||
return Add(title, nt::Value::MakeInteger(defaultValue));
|
||||
}
|
||||
|
||||
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
|
||||
@@ -120,6 +127,16 @@ SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
|
||||
return Add(title, nt::Value::MakeDoubleArray(defaultValue));
|
||||
}
|
||||
|
||||
SimpleWidget& ShuffleboardContainer::Add(std::string_view title,
|
||||
wpi::span<const float> defaultValue) {
|
||||
return Add(title, nt::Value::MakeFloatArray(defaultValue));
|
||||
}
|
||||
|
||||
SimpleWidget& ShuffleboardContainer::Add(
|
||||
std::string_view title, wpi::span<const int64_t> defaultValue) {
|
||||
return Add(title, nt::Value::MakeIntegerArray(defaultValue));
|
||||
}
|
||||
|
||||
SimpleWidget& ShuffleboardContainer::Add(
|
||||
std::string_view title, wpi::span<const std::string> defaultValue) {
|
||||
return Add(title, nt::Value::MakeStringArray(defaultValue));
|
||||
@@ -127,13 +144,13 @@ SimpleWidget& ShuffleboardContainer::Add(
|
||||
|
||||
SuppliedValueWidget<std::string>& ShuffleboardContainer::AddString(
|
||||
std::string_view title, std::function<std::string()> supplier) {
|
||||
static auto setter = [](nt::NetworkTableEntry entry, std::string value) {
|
||||
static auto setter = [](nt::GenericPublisher& entry, std::string value) {
|
||||
entry.SetString(value);
|
||||
};
|
||||
|
||||
CheckTitle(title);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<std::string>>(
|
||||
*this, title, supplier, setter);
|
||||
*this, title, "string", supplier, setter);
|
||||
auto ptr = widget.get();
|
||||
m_components.emplace_back(std::move(widget));
|
||||
return *ptr;
|
||||
@@ -141,13 +158,46 @@ SuppliedValueWidget<std::string>& ShuffleboardContainer::AddString(
|
||||
|
||||
SuppliedValueWidget<double>& ShuffleboardContainer::AddNumber(
|
||||
std::string_view title, std::function<double()> supplier) {
|
||||
static auto setter = [](nt::NetworkTableEntry entry, double value) {
|
||||
return AddDouble(title, std::move(supplier));
|
||||
}
|
||||
|
||||
SuppliedValueWidget<double>& ShuffleboardContainer::AddDouble(
|
||||
std::string_view title, std::function<double()> supplier) {
|
||||
static auto setter = [](nt::GenericPublisher& entry, double value) {
|
||||
entry.SetDouble(value);
|
||||
};
|
||||
|
||||
CheckTitle(title);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<double>>(*this, title,
|
||||
supplier, setter);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<double>>(
|
||||
*this, title, "double", supplier, setter);
|
||||
auto ptr = widget.get();
|
||||
m_components.emplace_back(std::move(widget));
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
SuppliedValueWidget<float>& ShuffleboardContainer::AddFloat(
|
||||
std::string_view title, std::function<float()> supplier) {
|
||||
static auto setter = [](nt::GenericPublisher& entry, float value) {
|
||||
entry.SetFloat(value);
|
||||
};
|
||||
|
||||
CheckTitle(title);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<float>>(
|
||||
*this, title, "float", supplier, setter);
|
||||
auto ptr = widget.get();
|
||||
m_components.emplace_back(std::move(widget));
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
SuppliedValueWidget<int64_t>& ShuffleboardContainer::AddInteger(
|
||||
std::string_view title, std::function<int64_t()> supplier) {
|
||||
static auto setter = [](nt::GenericPublisher& entry, int64_t value) {
|
||||
entry.SetInteger(value);
|
||||
};
|
||||
|
||||
CheckTitle(title);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<int64_t>>(
|
||||
*this, title, "int", supplier, setter);
|
||||
auto ptr = widget.get();
|
||||
m_components.emplace_back(std::move(widget));
|
||||
return *ptr;
|
||||
@@ -155,13 +205,13 @@ SuppliedValueWidget<double>& ShuffleboardContainer::AddNumber(
|
||||
|
||||
SuppliedValueWidget<bool>& ShuffleboardContainer::AddBoolean(
|
||||
std::string_view title, std::function<bool()> supplier) {
|
||||
static auto setter = [](nt::NetworkTableEntry entry, bool value) {
|
||||
static auto setter = [](nt::GenericPublisher& entry, bool value) {
|
||||
entry.SetBoolean(value);
|
||||
};
|
||||
|
||||
CheckTitle(title);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<bool>>(*this, title,
|
||||
supplier, setter);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<bool>>(
|
||||
*this, title, "boolean", supplier, setter);
|
||||
auto ptr = widget.get();
|
||||
m_components.emplace_back(std::move(widget));
|
||||
return *ptr;
|
||||
@@ -171,14 +221,14 @@ SuppliedValueWidget<std::vector<std::string>>&
|
||||
ShuffleboardContainer::AddStringArray(
|
||||
std::string_view title,
|
||||
std::function<std::vector<std::string>()> supplier) {
|
||||
static auto setter = [](nt::NetworkTableEntry entry,
|
||||
static auto setter = [](nt::GenericPublisher& entry,
|
||||
std::vector<std::string> value) {
|
||||
entry.SetStringArray(value);
|
||||
};
|
||||
|
||||
CheckTitle(title);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<std::vector<std::string>>>(
|
||||
*this, title, supplier, setter);
|
||||
*this, title, "string[]", supplier, setter);
|
||||
auto ptr = widget.get();
|
||||
m_components.emplace_back(std::move(widget));
|
||||
return *ptr;
|
||||
@@ -186,14 +236,50 @@ ShuffleboardContainer::AddStringArray(
|
||||
|
||||
SuppliedValueWidget<std::vector<double>>& ShuffleboardContainer::AddNumberArray(
|
||||
std::string_view title, std::function<std::vector<double>()> supplier) {
|
||||
static auto setter = [](nt::NetworkTableEntry entry,
|
||||
return AddDoubleArray(title, std::move(supplier));
|
||||
}
|
||||
|
||||
SuppliedValueWidget<std::vector<double>>& ShuffleboardContainer::AddDoubleArray(
|
||||
std::string_view title, std::function<std::vector<double>()> supplier) {
|
||||
static auto setter = [](nt::GenericPublisher& entry,
|
||||
std::vector<double> value) {
|
||||
entry.SetDoubleArray(value);
|
||||
};
|
||||
|
||||
CheckTitle(title);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<std::vector<double>>>(
|
||||
*this, title, supplier, setter);
|
||||
*this, title, "double[]", supplier, setter);
|
||||
auto ptr = widget.get();
|
||||
m_components.emplace_back(std::move(widget));
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
SuppliedValueWidget<std::vector<float>>& ShuffleboardContainer::AddFloatArray(
|
||||
std::string_view title, std::function<std::vector<float>()> supplier) {
|
||||
static auto setter = [](nt::GenericPublisher& entry,
|
||||
std::vector<float> value) {
|
||||
entry.SetFloatArray(value);
|
||||
};
|
||||
|
||||
CheckTitle(title);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<std::vector<float>>>(
|
||||
*this, title, "float[]", supplier, setter);
|
||||
auto ptr = widget.get();
|
||||
m_components.emplace_back(std::move(widget));
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
SuppliedValueWidget<std::vector<int64_t>>&
|
||||
ShuffleboardContainer::AddIntegerArray(
|
||||
std::string_view title, std::function<std::vector<int64_t>()> supplier) {
|
||||
static auto setter = [](nt::GenericPublisher& entry,
|
||||
std::vector<int64_t> value) {
|
||||
entry.SetIntegerArray(value);
|
||||
};
|
||||
|
||||
CheckTitle(title);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<std::vector<int64_t>>>(
|
||||
*this, title, "int[]", supplier, setter);
|
||||
auto ptr = widget.get();
|
||||
m_components.emplace_back(std::move(widget));
|
||||
return *ptr;
|
||||
@@ -201,36 +287,43 @@ SuppliedValueWidget<std::vector<double>>& ShuffleboardContainer::AddNumberArray(
|
||||
|
||||
SuppliedValueWidget<std::vector<int>>& ShuffleboardContainer::AddBooleanArray(
|
||||
std::string_view title, std::function<std::vector<int>()> supplier) {
|
||||
static auto setter = [](nt::NetworkTableEntry entry, std::vector<int> value) {
|
||||
static auto setter = [](nt::GenericPublisher& entry, std::vector<int> value) {
|
||||
entry.SetBooleanArray(value);
|
||||
};
|
||||
|
||||
CheckTitle(title);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<std::vector<int>>>(
|
||||
*this, title, supplier, setter);
|
||||
*this, title, "boolean[]", supplier, setter);
|
||||
auto ptr = widget.get();
|
||||
m_components.emplace_back(std::move(widget));
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
SuppliedValueWidget<std::string_view>& ShuffleboardContainer::AddRaw(
|
||||
std::string_view title, std::function<std::string_view()> supplier) {
|
||||
static auto setter = [](nt::NetworkTableEntry entry, std::string_view value) {
|
||||
entry.SetRaw(value);
|
||||
};
|
||||
SuppliedValueWidget<std::vector<uint8_t>>& ShuffleboardContainer::AddRaw(
|
||||
std::string_view title, std::function<std::vector<uint8_t>()> supplier) {
|
||||
return AddRaw(title, "raw", std::move(supplier));
|
||||
}
|
||||
|
||||
SuppliedValueWidget<std::vector<uint8_t>>& ShuffleboardContainer::AddRaw(
|
||||
std::string_view title, std::string_view typeString,
|
||||
std::function<std::vector<uint8_t>()> supplier) {
|
||||
static auto setter = [](nt::GenericPublisher& entry,
|
||||
std::vector<uint8_t> value) { entry.SetRaw(value); };
|
||||
|
||||
CheckTitle(title);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<std::string_view>>(
|
||||
*this, title, supplier, setter);
|
||||
auto widget = std::make_unique<SuppliedValueWidget<std::vector<uint8_t>>>(
|
||||
*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, std::shared_ptr<nt::Value> defaultValue) {
|
||||
std::string_view title, const nt::Value& defaultValue) {
|
||||
auto& widget = Add(title, defaultValue);
|
||||
widget.GetEntry().SetPersistent();
|
||||
widget.GetEntry(nt::GetStringFromType(defaultValue.type()))
|
||||
.GetTopic()
|
||||
.SetPersistent(true);
|
||||
return widget;
|
||||
}
|
||||
|
||||
@@ -244,9 +337,14 @@ SimpleWidget& ShuffleboardContainer::AddPersistent(std::string_view title,
|
||||
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::MakeDouble(defaultValue));
|
||||
return AddPersistent(title, nt::Value::MakeInteger(defaultValue));
|
||||
}
|
||||
|
||||
SimpleWidget& ShuffleboardContainer::AddPersistent(
|
||||
@@ -264,6 +362,16 @@ SimpleWidget& ShuffleboardContainer::AddPersistent(
|
||||
return AddPersistent(title, nt::Value::MakeDoubleArray(defaultValue));
|
||||
}
|
||||
|
||||
SimpleWidget& ShuffleboardContainer::AddPersistent(
|
||||
std::string_view title, wpi::span<const float> defaultValue) {
|
||||
return AddPersistent(title, nt::Value::MakeFloatArray(defaultValue));
|
||||
}
|
||||
|
||||
SimpleWidget& ShuffleboardContainer::AddPersistent(
|
||||
std::string_view title, wpi::span<const int64_t> defaultValue) {
|
||||
return AddPersistent(title, nt::Value::MakeIntegerArray(defaultValue));
|
||||
}
|
||||
|
||||
SimpleWidget& ShuffleboardContainer::AddPersistent(
|
||||
std::string_view title, wpi::span<const std::string> defaultValue) {
|
||||
return AddPersistent(title, nt::Value::MakeStringArray(defaultValue));
|
||||
|
||||
@@ -46,7 +46,7 @@ void ShuffleboardInstance::Update() {
|
||||
for (auto& entry : m_impl->tabs) {
|
||||
tabTitles.emplace_back(entry.second->GetTitle());
|
||||
}
|
||||
m_impl->rootMetaTable->GetEntry("Tabs").ForceSetStringArray(tabTitles);
|
||||
m_impl->rootMetaTable->GetEntry("Tabs").SetStringArray(tabTitles);
|
||||
m_impl->tabsChanged = false;
|
||||
}
|
||||
for (auto& entry : m_impl->tabs) {
|
||||
@@ -75,9 +75,9 @@ void ShuffleboardInstance::DisableActuatorWidgets() {
|
||||
}
|
||||
|
||||
void ShuffleboardInstance::SelectTab(int index) {
|
||||
m_impl->rootMetaTable->GetEntry("Selected").ForceSetDouble(index);
|
||||
m_impl->rootMetaTable->GetEntry("Selected").SetDouble(index);
|
||||
}
|
||||
|
||||
void ShuffleboardInstance::SelectTab(std::string_view title) {
|
||||
m_impl->rootMetaTable->GetEntry("Selected").ForceSetString(title);
|
||||
m_impl->rootMetaTable->GetEntry("Selected").SetString(title);
|
||||
}
|
||||
|
||||
@@ -14,18 +14,26 @@ SimpleWidget::SimpleWidget(ShuffleboardContainer& parent,
|
||||
std::string_view title)
|
||||
: ShuffleboardValue(title), ShuffleboardWidget(parent, title), m_entry() {}
|
||||
|
||||
nt::NetworkTableEntry SimpleWidget::GetEntry() {
|
||||
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<nt::NetworkTable> parentTable,
|
||||
std::shared_ptr<nt::NetworkTable> metaTable) {
|
||||
BuildMetadata(metaTable);
|
||||
if (!m_entry) {
|
||||
m_entry = parentTable->GetEntry(GetTitle());
|
||||
m_entry = parentTable->GetTopic(GetTitle()).GetGenericEntry(m_typeString);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "frc/smartdashboard/Field2d.h"
|
||||
|
||||
#include <networktables/DoubleArrayTopic.h>
|
||||
#include <networktables/NTSendableBuilder.h>
|
||||
#include <wpi/sendable/SendableRegistry.h>
|
||||
|
||||
@@ -57,7 +58,7 @@ FieldObject2d* Field2d::GetObject(std::string_view name) {
|
||||
std::make_unique<FieldObject2d>(name, FieldObject2d::private_init{}));
|
||||
auto obj = m_objects.back().get();
|
||||
if (m_table) {
|
||||
obj->m_entry = m_table->GetEntry(obj->m_name);
|
||||
obj->m_entry = m_table->GetDoubleArrayTopic(obj->m_name).GetEntry({});
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
@@ -74,7 +75,7 @@ void Field2d::InitSendable(nt::NTSendableBuilder& builder) {
|
||||
m_table = builder.GetTable();
|
||||
for (auto&& obj : m_objects) {
|
||||
std::scoped_lock lock2(obj->m_mutex);
|
||||
obj->m_entry = m_table->GetEntry(obj->m_name);
|
||||
obj->m_entry = m_table->GetDoubleArrayTopic(obj->m_name).GetEntry({});
|
||||
obj->UpdateEntry(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/Endian.h>
|
||||
#include <wpi/MathExtras.h>
|
||||
|
||||
#include "frc/trajectory/Trajectory.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -83,41 +80,17 @@ void FieldObject2d::UpdateEntry(bool setDefault) {
|
||||
if (!m_entry) {
|
||||
return;
|
||||
}
|
||||
if (m_poses.size() < (255 / 3)) {
|
||||
wpi::SmallVector<double, 9> arr;
|
||||
for (auto&& pose : m_poses) {
|
||||
auto& translation = pose.Translation();
|
||||
arr.push_back(translation.X().value());
|
||||
arr.push_back(translation.Y().value());
|
||||
arr.push_back(pose.Rotation().Degrees().value());
|
||||
}
|
||||
if (setDefault) {
|
||||
m_entry.SetDefaultDoubleArray(arr);
|
||||
} else {
|
||||
m_entry.ForceSetDoubleArray(arr);
|
||||
}
|
||||
wpi::SmallVector<double, 9> arr;
|
||||
for (auto&& pose : m_poses) {
|
||||
auto& translation = pose.Translation();
|
||||
arr.push_back(translation.X().value());
|
||||
arr.push_back(translation.Y().value());
|
||||
arr.push_back(pose.Rotation().Degrees().value());
|
||||
}
|
||||
if (setDefault) {
|
||||
m_entry.SetDefault(arr);
|
||||
} else {
|
||||
// send as raw array of doubles if too big for NT array
|
||||
std::vector<char> arr;
|
||||
arr.resize(m_poses.size() * 3 * 8);
|
||||
char* p = arr.data();
|
||||
for (auto&& pose : m_poses) {
|
||||
auto& translation = pose.Translation();
|
||||
wpi::support::endian::write64be(
|
||||
p, wpi::DoubleToBits(translation.X().value()));
|
||||
p += 8;
|
||||
wpi::support::endian::write64be(
|
||||
p, wpi::DoubleToBits(translation.Y().value()));
|
||||
p += 8;
|
||||
wpi::support::endian::write64be(
|
||||
p, wpi::DoubleToBits(pose.Rotation().Degrees().value()));
|
||||
p += 8;
|
||||
}
|
||||
if (setDefault) {
|
||||
m_entry.SetDefaultRaw({arr.data(), arr.size()});
|
||||
} else {
|
||||
m_entry.ForceSetRaw({arr.data(), arr.size()});
|
||||
}
|
||||
m_entry.Set(arr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,46 +98,15 @@ void FieldObject2d::UpdateFromEntry() const {
|
||||
if (!m_entry) {
|
||||
return;
|
||||
}
|
||||
auto val = m_entry.GetValue();
|
||||
if (!val) {
|
||||
auto arr = m_entry.Get();
|
||||
auto size = arr.size();
|
||||
if ((size % 3) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (val->IsDoubleArray()) {
|
||||
auto arr = val->GetDoubleArray();
|
||||
auto size = arr.size();
|
||||
if ((size % 3) != 0) {
|
||||
return;
|
||||
}
|
||||
m_poses.resize(size / 3);
|
||||
for (size_t i = 0; i < size / 3; ++i) {
|
||||
m_poses[i] =
|
||||
Pose2d{units::meter_t{arr[i * 3 + 0]}, units::meter_t{arr[i * 3 + 1]},
|
||||
units::degree_t{arr[i * 3 + 2]}};
|
||||
}
|
||||
} else if (val->IsRaw()) {
|
||||
// treat it simply as an array of doubles
|
||||
std::string_view data = val->GetRaw();
|
||||
|
||||
// must be triples of doubles
|
||||
auto size = data.size();
|
||||
if ((size % (3 * 8)) != 0) {
|
||||
return;
|
||||
}
|
||||
m_poses.resize(size / (3 * 8));
|
||||
const char* p = data.data();
|
||||
for (size_t i = 0; i < size / (3 * 8); ++i) {
|
||||
double x = wpi::BitsToDouble(
|
||||
wpi::support::endian::readNext<uint64_t, wpi::support::big,
|
||||
wpi::support::unaligned>(p));
|
||||
double y = wpi::BitsToDouble(
|
||||
wpi::support::endian::readNext<uint64_t, wpi::support::big,
|
||||
wpi::support::unaligned>(p));
|
||||
double rot = wpi::BitsToDouble(
|
||||
wpi::support::endian::readNext<uint64_t, wpi::support::big,
|
||||
wpi::support::unaligned>(p));
|
||||
m_poses[i] =
|
||||
Pose2d{units::meter_t{x}, units::meter_t{y}, units::degree_t{rot}};
|
||||
}
|
||||
m_poses.resize(size / 3);
|
||||
for (size_t i = 0; i < size / 3; ++i) {
|
||||
m_poses[i] =
|
||||
Pose2d{units::meter_t{arr[i * 3 + 0]}, units::meter_t{arr[i * 3 + 1]},
|
||||
units::degree_t{arr[i * 3 + 2]}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
#include "frc/smartdashboard/Mechanism2d.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string_view>
|
||||
|
||||
#include <networktables/NTSendableBuilder.h>
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static constexpr char kBackgroundColor[] = "backgroundColor";
|
||||
static constexpr char kDims[] = "dims";
|
||||
static constexpr std::string_view kBackgroundColor = "backgroundColor";
|
||||
static constexpr std::string_view kDims = "dims";
|
||||
|
||||
Mechanism2d::Mechanism2d(double width, double height,
|
||||
const Color8Bit& backgroundColor)
|
||||
@@ -35,8 +36,8 @@ MechanismRoot2d* Mechanism2d::GetRoot(std::string_view name, double x,
|
||||
|
||||
void Mechanism2d::SetBackgroundColor(const Color8Bit& color) {
|
||||
m_color = color.HexString();
|
||||
if (m_table) {
|
||||
m_table->GetEntry(kBackgroundColor).SetString(m_color);
|
||||
if (m_colorPub) {
|
||||
m_colorPub.Set(m_color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +46,10 @@ void Mechanism2d::InitSendable(nt::NTSendableBuilder& builder) {
|
||||
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_table = builder.GetTable();
|
||||
m_table->GetEntry(kDims).SetDoubleArray({m_width, m_height});
|
||||
m_table->GetEntry(kBackgroundColor).SetString(m_color);
|
||||
m_dimsPub = m_table->GetDoubleArrayTopic(kDims).Publish();
|
||||
m_dimsPub.Set({{m_width, m_height}});
|
||||
m_colorPub = m_table->GetStringTopic(kBackgroundColor).Publish();
|
||||
m_colorPub.Set(m_color);
|
||||
for (const auto& entry : m_roots) {
|
||||
const auto& root = entry.getValue().get();
|
||||
root->Update(m_table->GetSubTable(entry.getKey()));
|
||||
|
||||
@@ -21,38 +21,48 @@ MechanismLigament2d::MechanismLigament2d(std::string_view name, double length,
|
||||
|
||||
void MechanismLigament2d::UpdateEntries(
|
||||
std::shared_ptr<nt::NetworkTable> table) {
|
||||
table->GetEntry(".type").SetString("line");
|
||||
m_typePub = table->GetStringTopic(".type").Publish();
|
||||
m_typePub.Set("line");
|
||||
|
||||
m_colorEntry = table->GetEntry("color");
|
||||
m_angleEntry = table->GetEntry("angle");
|
||||
m_weightEntry = table->GetEntry("weight");
|
||||
m_lengthEntry = table->GetEntry("length");
|
||||
Flush();
|
||||
m_colorEntry = table->GetStringTopic("color").GetEntry("");
|
||||
m_colorEntry.Set(m_color);
|
||||
m_angleEntry = table->GetDoubleTopic("angle").GetEntry(0.0);
|
||||
m_angleEntry.Set(m_angle);
|
||||
m_weightEntry = table->GetDoubleTopic("weight").GetEntry(0.0);
|
||||
m_weightEntry.Set(m_weight);
|
||||
m_lengthEntry = table->GetDoubleTopic("length").GetEntry(0.0);
|
||||
m_lengthEntry.Set(m_length);
|
||||
}
|
||||
|
||||
void MechanismLigament2d::SetColor(const Color8Bit& color) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
std::snprintf(m_color, sizeof(m_color), "#%02X%02X%02X", color.red,
|
||||
color.green, color.blue);
|
||||
Flush();
|
||||
if (m_colorEntry) {
|
||||
m_colorEntry.Set(m_color);
|
||||
}
|
||||
}
|
||||
|
||||
void MechanismLigament2d::SetAngle(units::degree_t angle) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_angle = angle.value();
|
||||
Flush();
|
||||
if (m_angleEntry) {
|
||||
m_angleEntry.Set(m_angle);
|
||||
}
|
||||
}
|
||||
|
||||
void MechanismLigament2d::SetLineWeight(double lineWidth) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_weight = lineWidth;
|
||||
Flush();
|
||||
if (m_weightEntry) {
|
||||
m_weightEntry.Set(m_weight);
|
||||
}
|
||||
}
|
||||
|
||||
Color8Bit MechanismLigament2d::GetColor() {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (m_colorEntry) {
|
||||
auto color = m_colorEntry.GetString("");
|
||||
auto color = m_colorEntry.Get();
|
||||
std::strncpy(m_color, color.c_str(), sizeof(m_color));
|
||||
m_color[sizeof(m_color) - 1] = '\0';
|
||||
}
|
||||
@@ -64,7 +74,7 @@ Color8Bit MechanismLigament2d::GetColor() {
|
||||
double MechanismLigament2d::GetAngle() {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (m_angleEntry) {
|
||||
m_angle = m_angleEntry.GetDouble(0.0);
|
||||
m_angle = m_angleEntry.Get();
|
||||
}
|
||||
return m_angle;
|
||||
}
|
||||
@@ -72,7 +82,7 @@ double MechanismLigament2d::GetAngle() {
|
||||
double MechanismLigament2d::GetLength() {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (m_lengthEntry) {
|
||||
m_length = m_lengthEntry.GetDouble(0.0);
|
||||
m_length = m_lengthEntry.Get();
|
||||
}
|
||||
return m_length;
|
||||
}
|
||||
@@ -80,7 +90,7 @@ double MechanismLigament2d::GetLength() {
|
||||
double MechanismLigament2d::GetLineWeight() {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (m_weightEntry) {
|
||||
m_weight = m_weightEntry.GetDouble(0.0);
|
||||
m_weight = m_weightEntry.Get();
|
||||
}
|
||||
return m_weight;
|
||||
}
|
||||
@@ -88,16 +98,7 @@ double MechanismLigament2d::GetLineWeight() {
|
||||
void MechanismLigament2d::SetLength(double length) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_length = length;
|
||||
Flush();
|
||||
}
|
||||
|
||||
#define SAFE_WRITE(data, Type) \
|
||||
if (m_##data##Entry) { \
|
||||
m_##data##Entry.Set##Type(m_##data); \
|
||||
if (m_lengthEntry) {
|
||||
m_lengthEntry.Set(length);
|
||||
}
|
||||
void MechanismLigament2d::Flush() {
|
||||
SAFE_WRITE(color, String)
|
||||
SAFE_WRITE(angle, Double)
|
||||
SAFE_WRITE(length, Double)
|
||||
SAFE_WRITE(weight, Double)
|
||||
}
|
||||
|
||||
@@ -20,16 +20,16 @@ void MechanismRoot2d::SetPosition(double x, double y) {
|
||||
}
|
||||
|
||||
void MechanismRoot2d::UpdateEntries(std::shared_ptr<nt::NetworkTable> table) {
|
||||
m_xEntry = table->GetEntry("x");
|
||||
m_yEntry = table->GetEntry("y");
|
||||
m_xPub = table->GetDoubleTopic("x").Publish();
|
||||
m_yPub = table->GetDoubleTopic("y").Publish();
|
||||
Flush();
|
||||
}
|
||||
|
||||
inline void MechanismRoot2d::Flush() {
|
||||
if (m_xEntry) {
|
||||
m_xEntry.SetDouble(m_x);
|
||||
if (m_xPub) {
|
||||
m_xPub.Set(m_x);
|
||||
}
|
||||
if (m_yEntry) {
|
||||
m_yEntry.SetDouble(m_y);
|
||||
if (m_yPub) {
|
||||
m_yPub.Set(m_y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,37 @@
|
||||
|
||||
#include "frc/smartdashboard/SendableBuilderImpl.h"
|
||||
|
||||
#include <networktables/BooleanArrayTopic.h>
|
||||
#include <networktables/BooleanTopic.h>
|
||||
#include <networktables/DoubleArrayTopic.h>
|
||||
#include <networktables/DoubleTopic.h>
|
||||
#include <networktables/FloatArrayTopic.h>
|
||||
#include <networktables/FloatTopic.h>
|
||||
#include <networktables/IntegerArrayTopic.h>
|
||||
#include <networktables/IntegerTopic.h>
|
||||
#include <networktables/RawTopic.h>
|
||||
#include <networktables/StringArrayTopic.h>
|
||||
#include <ntcore_cpp.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "frc/smartdashboard/SmartDashboard.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
template <typename Topic>
|
||||
void SendableBuilderImpl::PropertyImpl<Topic>::Update(bool controllable,
|
||||
int64_t time) {
|
||||
if (controllable && sub && updateLocal) {
|
||||
updateLocal(sub);
|
||||
} else if (pub && updateNetwork) {
|
||||
updateNetwork(pub, time);
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::SetTable(std::shared_ptr<nt::NetworkTable> table) {
|
||||
m_table = table;
|
||||
m_controllableEntry = table->GetEntry(".controllable");
|
||||
m_controllablePublisher = table->GetBooleanTopic(".controllable").Publish();
|
||||
m_controllablePublisher.SetDefault(false);
|
||||
}
|
||||
|
||||
std::shared_ptr<nt::NetworkTable> SendableBuilderImpl::GetTable() {
|
||||
@@ -31,9 +52,7 @@ bool SendableBuilderImpl::IsActuator() const {
|
||||
void SendableBuilderImpl::Update() {
|
||||
uint64_t time = nt::Now();
|
||||
for (auto& property : m_properties) {
|
||||
if (property.update) {
|
||||
property.update(property.entry, time);
|
||||
}
|
||||
property->Update(m_controllable, time);
|
||||
}
|
||||
for (auto& updateTable : m_updateTables) {
|
||||
updateTable();
|
||||
@@ -41,20 +60,16 @@ void SendableBuilderImpl::Update() {
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::StartListeners() {
|
||||
for (auto& property : m_properties) {
|
||||
property.StartListener();
|
||||
}
|
||||
if (m_controllableEntry) {
|
||||
m_controllableEntry.SetBoolean(true);
|
||||
m_controllable = true;
|
||||
if (m_controllablePublisher) {
|
||||
m_controllablePublisher.Set(true);
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::StopListeners() {
|
||||
for (auto& property : m_properties) {
|
||||
property.StopListener();
|
||||
}
|
||||
if (m_controllableEntry) {
|
||||
m_controllableEntry.SetBoolean(false);
|
||||
m_controllable = false;
|
||||
if (m_controllablePublisher) {
|
||||
m_controllablePublisher.Set(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,11 +92,17 @@ void SendableBuilderImpl::ClearProperties() {
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::SetSmartDashboardType(std::string_view type) {
|
||||
m_table->GetEntry(".type").SetString(type);
|
||||
if (!m_typePublisher) {
|
||||
m_typePublisher = m_table->GetStringTopic(".type").Publish();
|
||||
}
|
||||
m_typePublisher.Set(type);
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::SetActuator(bool value) {
|
||||
m_table->GetEntry(".actuator").SetBoolean(value);
|
||||
if (!m_actuatorPublisher) {
|
||||
m_actuatorPublisher = m_table->GetBooleanTopic(".actuator").Publish();
|
||||
}
|
||||
m_actuatorPublisher.Set(value);
|
||||
m_actuator = value;
|
||||
}
|
||||
|
||||
@@ -89,272 +110,183 @@ void SendableBuilderImpl::SetSafeState(std::function<void()> func) {
|
||||
m_safeState = func;
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::SetUpdateTable(std::function<void()> func) {
|
||||
void SendableBuilderImpl::SetUpdateTable(wpi::unique_function<void()> func) {
|
||||
m_updateTables.emplace_back(std::move(func));
|
||||
}
|
||||
|
||||
nt::NetworkTableEntry SendableBuilderImpl::GetEntry(std::string_view key) {
|
||||
return m_table->GetEntry(key);
|
||||
nt::Topic SendableBuilderImpl::GetTopic(std::string_view key) {
|
||||
return m_table->GetTopic(key);
|
||||
}
|
||||
|
||||
template <typename Topic, typename Getter, typename Setter>
|
||||
void SendableBuilderImpl::AddPropertyImpl(Topic topic, Getter getter,
|
||||
Setter setter) {
|
||||
auto prop = std::make_unique<PropertyImpl<Topic>>();
|
||||
if (getter) {
|
||||
prop->pub = topic.Publish();
|
||||
prop->updateNetwork = [=](auto& pub, int64_t time) {
|
||||
pub.Set(getter(), time);
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
prop->sub = topic.Subscribe({});
|
||||
prop->updateLocal = [=](auto& sub) {
|
||||
for (auto&& val : sub.ReadQueue()) {
|
||||
setter(val.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
m_properties.emplace_back(std::move(prop));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddBooleanProperty(std::string_view key,
|
||||
std::function<bool()> getter,
|
||||
std::function<void(bool)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeBoolean(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsBoolean()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetBoolean()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
AddPropertyImpl(m_table->GetBooleanTopic(key), std::move(getter),
|
||||
std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddIntegerProperty(
|
||||
std::string_view key, std::function<int64_t()> getter,
|
||||
std::function<void(int64_t)> setter) {
|
||||
AddPropertyImpl(m_table->GetIntegerTopic(key), std::move(getter),
|
||||
std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddFloatProperty(std::string_view key,
|
||||
std::function<float()> getter,
|
||||
std::function<void(float)> setter) {
|
||||
AddPropertyImpl(m_table->GetFloatTopic(key), std::move(getter),
|
||||
std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddDoubleProperty(
|
||||
std::string_view key, std::function<double()> getter,
|
||||
std::function<void(double)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeDouble(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDouble()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetDouble()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
AddPropertyImpl(m_table->GetDoubleTopic(key), std::move(getter),
|
||||
std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddStringProperty(
|
||||
std::string_view key, std::function<std::string()> getter,
|
||||
std::function<void(std::string_view)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeString(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsString()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetString()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
AddPropertyImpl(m_table->GetStringTopic(key), std::move(getter),
|
||||
std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddBooleanArrayProperty(
|
||||
std::string_view key, std::function<std::vector<int>()> getter,
|
||||
std::function<void(wpi::span<const int>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeBooleanArray(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsBooleanArray()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetBooleanArray()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
AddPropertyImpl(m_table->GetBooleanArrayTopic(key), std::move(getter),
|
||||
std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddIntegerArrayProperty(
|
||||
std::string_view key, std::function<std::vector<int64_t>()> getter,
|
||||
std::function<void(wpi::span<const int64_t>)> setter) {
|
||||
AddPropertyImpl(m_table->GetIntegerArrayTopic(key), std::move(getter),
|
||||
std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddFloatArrayProperty(
|
||||
std::string_view key, std::function<std::vector<float>()> getter,
|
||||
std::function<void(wpi::span<const float>)> setter) {
|
||||
AddPropertyImpl(m_table->GetFloatArrayTopic(key), std::move(getter),
|
||||
std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddDoubleArrayProperty(
|
||||
std::string_view key, std::function<std::vector<double>()> getter,
|
||||
std::function<void(wpi::span<const double>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeDoubleArray(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDoubleArray()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetDoubleArray()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
AddPropertyImpl(m_table->GetDoubleArrayTopic(key), std::move(getter),
|
||||
std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddStringArrayProperty(
|
||||
std::string_view key, std::function<std::vector<std::string>()> getter,
|
||||
std::function<void(wpi::span<const std::string>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeStringArray(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsStringArray()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetStringArray()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
AddPropertyImpl(m_table->GetStringArrayTopic(key), std::move(getter),
|
||||
std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddRawProperty(
|
||||
std::string_view key, std::function<std::string()> getter,
|
||||
std::function<void(std::string_view)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
std::string_view key, std::string_view typeString,
|
||||
std::function<std::vector<uint8_t>()> getter,
|
||||
std::function<void(wpi::span<const uint8_t>)> setter) {
|
||||
auto topic = m_table->GetRawTopic(key);
|
||||
auto prop = std::make_unique<PropertyImpl<nt::RawTopic>>();
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeRaw(getter(), time));
|
||||
prop->pub = topic.Publish(typeString);
|
||||
prop->updateNetwork = [=](auto& pub, int64_t time) {
|
||||
pub.Set(getter(), time);
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsRaw()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetRaw()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
prop->sub = topic.Subscribe(typeString, {});
|
||||
prop->updateLocal = [=](auto& sub) {
|
||||
for (auto&& val : sub.ReadQueue()) {
|
||||
setter(val.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
m_properties.emplace_back(std::move(prop));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddValueProperty(
|
||||
std::string_view key, std::function<std::shared_ptr<nt::Value>()> getter,
|
||||
std::function<void(std::shared_ptr<nt::Value>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
template <typename T, size_t Size, typename Topic, typename Getter,
|
||||
typename Setter>
|
||||
void SendableBuilderImpl::AddSmallPropertyImpl(Topic topic, Getter getter,
|
||||
Setter setter) {
|
||||
auto prop = std::make_unique<PropertyImpl<Topic>>();
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(getter());
|
||||
prop->pub = topic.Publish();
|
||||
prop->updateNetwork = [=](auto& pub, int64_t time) {
|
||||
wpi::SmallVector<T, Size> buf;
|
||||
pub.Set(getter(buf), time);
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
SmartDashboard::PostListenerTask([=] { setter(event.value); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
prop->sub = topic.Subscribe({});
|
||||
prop->updateLocal = [=](auto& sub) {
|
||||
for (auto&& val : sub.ReadQueue()) {
|
||||
setter(val.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
m_properties.emplace_back(std::move(prop));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallStringProperty(
|
||||
std::string_view key,
|
||||
std::function<std::string_view(wpi::SmallVectorImpl<char>& buf)> getter,
|
||||
std::function<void(std::string_view)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
wpi::SmallString<128> buf;
|
||||
entry.SetValue(nt::Value::MakeString(getter(buf), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsString()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetString()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
AddSmallPropertyImpl<char, 128>(m_table->GetStringTopic(key),
|
||||
std::move(getter), std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallBooleanArrayProperty(
|
||||
std::string_view key,
|
||||
std::function<wpi::span<const int>(wpi::SmallVectorImpl<int>& buf)> getter,
|
||||
std::function<void(wpi::span<const int>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
wpi::SmallVector<int, 16> buf;
|
||||
entry.SetValue(nt::Value::MakeBooleanArray(getter(buf), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsBooleanArray()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetBooleanArray()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
AddSmallPropertyImpl<int, 16>(m_table->GetBooleanArrayTopic(key),
|
||||
std::move(getter), std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallIntegerArrayProperty(
|
||||
std::string_view key,
|
||||
std::function<wpi::span<const int64_t>(wpi::SmallVectorImpl<int64_t>& buf)>
|
||||
getter,
|
||||
std::function<void(wpi::span<const int64_t>)> setter) {
|
||||
AddSmallPropertyImpl<int64_t, 16>(m_table->GetIntegerArrayTopic(key),
|
||||
std::move(getter), std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallFloatArrayProperty(
|
||||
std::string_view key,
|
||||
std::function<wpi::span<const float>(wpi::SmallVectorImpl<float>& buf)>
|
||||
getter,
|
||||
std::function<void(wpi::span<const float>)> setter) {
|
||||
AddSmallPropertyImpl<float, 16>(m_table->GetFloatArrayTopic(key),
|
||||
std::move(getter), std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallDoubleArrayProperty(
|
||||
@@ -362,28 +294,8 @@ void SendableBuilderImpl::AddSmallDoubleArrayProperty(
|
||||
std::function<wpi::span<const double>(wpi::SmallVectorImpl<double>& buf)>
|
||||
getter,
|
||||
std::function<void(wpi::span<const double>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
wpi::SmallVector<double, 16> buf;
|
||||
entry.SetValue(nt::Value::MakeDoubleArray(getter(buf), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDoubleArray()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetDoubleArray()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
AddSmallPropertyImpl<double, 16>(m_table->GetDoubleArrayTopic(key),
|
||||
std::move(getter), std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallStringArrayProperty(
|
||||
@@ -392,54 +304,31 @@ void SendableBuilderImpl::AddSmallStringArrayProperty(
|
||||
wpi::span<const std::string>(wpi::SmallVectorImpl<std::string>& buf)>
|
||||
getter,
|
||||
std::function<void(wpi::span<const std::string>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
wpi::SmallVector<std::string, 16> buf;
|
||||
entry.SetValue(nt::Value::MakeStringArray(getter(buf), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsStringArray()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetStringArray()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
AddSmallPropertyImpl<std::string, 16>(m_table->GetStringArrayTopic(key),
|
||||
std::move(getter), std::move(setter));
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallRawProperty(
|
||||
std::string_view key,
|
||||
std::function<std::string_view(wpi::SmallVectorImpl<char>& buf)> getter,
|
||||
std::function<void(std::string_view)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
std::string_view key, std::string_view typeString,
|
||||
std::function<wpi::span<uint8_t>(wpi::SmallVectorImpl<uint8_t>& buf)>
|
||||
getter,
|
||||
std::function<void(wpi::span<const uint8_t>)> setter) {
|
||||
auto topic = m_table->GetRawTopic(key);
|
||||
auto prop = std::make_unique<PropertyImpl<nt::RawTopic>>();
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
wpi::SmallVector<char, 128> buf;
|
||||
entry.SetValue(nt::Value::MakeRaw(getter(buf), time));
|
||||
prop->pub = topic.Publish(typeString);
|
||||
prop->updateNetwork = [=](auto& pub, int64_t time) {
|
||||
wpi::SmallVector<uint8_t, 128> buf;
|
||||
pub.Set(getter(buf), time);
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsRaw()) {
|
||||
return;
|
||||
}
|
||||
SmartDashboard::PostListenerTask(
|
||||
[=] { setter(event.value->GetRaw()); });
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
prop->sub = topic.Subscribe(typeString, {});
|
||||
prop->updateLocal = [=](auto& sub) {
|
||||
for (auto&& val : sub.ReadQueue()) {
|
||||
setter(val.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
m_properties.emplace_back(std::move(prop));
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ SendableChooserBase::SendableChooserBase(SendableChooserBase&& oth)
|
||||
m_defaultChoice(std::move(oth.m_defaultChoice)),
|
||||
m_selected(std::move(oth.m_selected)),
|
||||
m_haveSelected(std::move(oth.m_haveSelected)),
|
||||
m_activeEntries(std::move(oth.m_activeEntries)),
|
||||
m_instancePubs(std::move(oth.m_instancePubs)),
|
||||
m_activePubs(std::move(oth.m_activePubs)),
|
||||
m_instance(std::move(oth.m_instance)) {}
|
||||
|
||||
SendableChooserBase& SendableChooserBase::operator=(SendableChooserBase&& oth) {
|
||||
@@ -28,7 +29,8 @@ SendableChooserBase& SendableChooserBase::operator=(SendableChooserBase&& oth) {
|
||||
m_defaultChoice = std::move(oth.m_defaultChoice);
|
||||
m_selected = std::move(oth.m_selected);
|
||||
m_haveSelected = std::move(oth.m_haveSelected);
|
||||
m_activeEntries = std::move(oth.m_activeEntries);
|
||||
m_instancePubs = std::move(oth.m_instancePubs);
|
||||
m_activePubs = std::move(oth.m_activePubs);
|
||||
m_instance = std::move(oth.m_instance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -70,22 +70,6 @@ bool SmartDashboard::IsPersistent(std::string_view key) {
|
||||
return GetInstance().table->GetEntry(key).IsPersistent();
|
||||
}
|
||||
|
||||
void SmartDashboard::SetFlags(std::string_view key, unsigned int flags) {
|
||||
GetInstance().table->GetEntry(key).SetFlags(flags);
|
||||
}
|
||||
|
||||
void SmartDashboard::ClearFlags(std::string_view key, unsigned int flags) {
|
||||
GetInstance().table->GetEntry(key).ClearFlags(flags);
|
||||
}
|
||||
|
||||
unsigned int SmartDashboard::GetFlags(std::string_view key) {
|
||||
return GetInstance().table->GetEntry(key).GetFlags();
|
||||
}
|
||||
|
||||
void SmartDashboard::Delete(std::string_view key) {
|
||||
GetInstance().table->Delete(key);
|
||||
}
|
||||
|
||||
nt::NetworkTableEntry SmartDashboard::GetEntry(std::string_view key) {
|
||||
return GetInstance().table->GetEntry(key);
|
||||
}
|
||||
@@ -218,31 +202,32 @@ std::vector<std::string> SmartDashboard::GetStringArray(
|
||||
return GetInstance().table->GetEntry(key).GetStringArray(defaultValue);
|
||||
}
|
||||
|
||||
bool SmartDashboard::PutRaw(std::string_view key, std::string_view value) {
|
||||
bool SmartDashboard::PutRaw(std::string_view key,
|
||||
wpi::span<const uint8_t> value) {
|
||||
return GetInstance().table->GetEntry(key).SetRaw(value);
|
||||
}
|
||||
|
||||
bool SmartDashboard::SetDefaultRaw(std::string_view key,
|
||||
std::string_view defaultValue) {
|
||||
wpi::span<const uint8_t> defaultValue) {
|
||||
return GetInstance().table->GetEntry(key).SetDefaultRaw(defaultValue);
|
||||
}
|
||||
|
||||
std::string SmartDashboard::GetRaw(std::string_view key,
|
||||
std::string_view defaultValue) {
|
||||
std::vector<uint8_t> SmartDashboard::GetRaw(
|
||||
std::string_view key, wpi::span<const uint8_t> defaultValue) {
|
||||
return GetInstance().table->GetEntry(key).GetRaw(defaultValue);
|
||||
}
|
||||
|
||||
bool SmartDashboard::PutValue(std::string_view keyName,
|
||||
std::shared_ptr<nt::Value> value) {
|
||||
const nt::Value& value) {
|
||||
return GetInstance().table->GetEntry(keyName).SetValue(value);
|
||||
}
|
||||
|
||||
bool SmartDashboard::SetDefaultValue(std::string_view key,
|
||||
std::shared_ptr<nt::Value> defaultValue) {
|
||||
const nt::Value& defaultValue) {
|
||||
return GetInstance().table->GetEntry(key).SetDefaultValue(defaultValue);
|
||||
}
|
||||
|
||||
std::shared_ptr<nt::Value> SmartDashboard::GetValue(std::string_view keyName) {
|
||||
nt::Value SmartDashboard::GetValue(std::string_view keyName) {
|
||||
return GetInstance().table->GetEntry(keyName).GetValue();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user