YAMS
Yet Another Mechanism System
Loading...
Searching...
No Matches
StructArrayTelemetry.hpp
Go to the documentation of this file.
1// Copyright (c) 2026 Yet Another Software Suite
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4#pragma once
5
6#include <algorithm>
7#include <memory>
8#include <optional>
9#include <span>
10#include <stdexcept>
11#include <string>
12#include <utility>
13#include <vector>
14#include <wpi/datalog/DataLog.hpp>
15#include <wpi/nt/NetworkTable.hpp>
16#include <wpi/nt/StructArrayTopic.hpp>
17#include <wpi/system/DataLogManager.hpp>
18#include <wpi/util/struct/Struct.hpp>
19
20namespace yams::telemetry {
21
31template <typename T, typename F>
33 public:
42 StructArrayTelemetry(std::string key, std::vector<T> defaultVal, F field, bool tunable)
43 : m_field{field},
44 m_key{std::move(key)},
45 m_tunable{tunable},
46 m_defaultValue{std::move(defaultVal)},
47 m_cachedValue{m_defaultValue} {}
48
54 void SetDefaultValue(std::vector<T> value) { m_cachedValue = m_defaultValue = std::move(value); }
55
62 void SetupNetworkTables(std::shared_ptr<wpi::nt::NetworkTable> dataTable,
63 std::shared_ptr<wpi::nt::NetworkTable> tuningTable) {
64 m_dataTable = dataTable;
65 m_tuningTable = tuningTable;
66 if (!m_enabled) return;
67
68 if (tuningTable && m_tunable) {
69 auto topic = tuningTable->template GetStructArrayTopic<T>(m_key);
70 m_subPublisher = topic.Publish();
71 m_subPublisher->SetDefault(m_defaultValue);
72 m_subscriber = topic.Subscribe(m_defaultValue);
73 } else if (dataTable) {
74 auto topic = dataTable->template GetStructArrayTopic<T>(m_key);
75 m_publisher = topic.Publish();
76 m_publisher->SetDefault(m_defaultValue);
77 }
78 }
79
85 void SetupNetworkTable(std::shared_ptr<wpi::nt::NetworkTable> dataTable) {
86 SetupNetworkTables(dataTable, nullptr);
87 }
88
94 void SetupDataLog(const std::string& prefix) {
95 if (m_tunable) return;
96 std::string path = prefix;
97 if (!path.empty() && path.back() != '/') path += '/';
98 path += m_key;
99 m_dataLogEntry = wpi::log::StructArrayLogEntry<T>{wpi::DataLogManager::GetLog(), path};
100 }
101
108 bool Set(std::span<const T> value) {
109 if (!m_enabled) return false;
110 if (m_dataLogEntry) {
111 m_dataLogEntry->Append(value);
112 }
113 if (m_subscriber) {
114 std::vector<T> tuningValue = m_subscriber->Get(m_defaultValue);
115 if (!(tuningValue.size() == value.size() &&
116 std::equal(tuningValue.begin(), tuningValue.end(), value.begin()))) {
117 return false;
118 }
119 }
120 if (m_publisher) {
121 m_publisher->Set(value);
122 }
123 return true;
124 }
125
131 std::vector<T> Get() const {
132 if (!m_enabled) return m_defaultValue;
133 if (m_subscriber) {
134 return m_subscriber->Get(m_defaultValue);
135 }
136 throw std::runtime_error("Tuning table not configured for " + m_key + "!");
137 }
138
144 bool IsTunable() {
145 if (m_subscriber && m_tunable && m_enabled) {
146 std::vector<T> current = m_subscriber->Get(m_defaultValue);
147 if (current != m_cachedValue) {
148 m_cachedValue = current;
149 return true;
150 }
151 }
152 return false;
153 }
154
156 void Enable() { m_enabled = true; }
158 void Disable() { m_enabled = false; }
164 void Display(bool state) { m_enabled = state; }
166 F GetField() const { return m_field; }
168 bool IsEnabled() const { return m_enabled; }
169
171 void Close() {
172 m_subscriber.reset();
173 m_subPublisher.reset();
174 m_publisher.reset();
175 if (m_dataTable) {
176 m_dataTable->GetEntry(m_key).Unpublish();
177 }
178 if (m_tuningTable) {
179 m_tuningTable->GetEntry(m_key).Unpublish();
180 }
181 }
182
183 private:
184 F m_field;
185 std::string m_key;
186 bool m_tunable;
187 bool m_enabled{false};
188 std::vector<T> m_defaultValue;
189 std::vector<T> m_cachedValue;
190
191 std::optional<wpi::nt::StructArrayPublisher<T>> m_publisher;
192 std::optional<wpi::nt::StructArraySubscriber<T>> m_subscriber;
193 std::optional<wpi::nt::StructArrayPublisher<T>> m_subPublisher; // tunable: publish + subscribe
194 std::optional<wpi::log::StructArrayLogEntry<T>> m_dataLogEntry;
195
196 std::shared_ptr<wpi::nt::NetworkTable> m_tuningTable;
197 std::shared_ptr<wpi::nt::NetworkTable> m_dataTable;
198};
199
200} // namespace yams::telemetry
Definition StructArrayTelemetry.hpp:32
void Disable()
Definition StructArrayTelemetry.hpp:158
bool IsEnabled() const
Definition StructArrayTelemetry.hpp:168
std::vector< T > Get() const
Definition StructArrayTelemetry.hpp:131
void SetDefaultValue(std::vector< T > value)
Definition StructArrayTelemetry.hpp:54
bool IsTunable()
Definition StructArrayTelemetry.hpp:144
void Close()
Definition StructArrayTelemetry.hpp:171
StructArrayTelemetry(std::string key, std::vector< T > defaultVal, F field, bool tunable)
Definition StructArrayTelemetry.hpp:42
F GetField() const
Definition StructArrayTelemetry.hpp:166
void SetupNetworkTable(std::shared_ptr< wpi::nt::NetworkTable > dataTable)
Definition StructArrayTelemetry.hpp:85
void SetupDataLog(const std::string &prefix)
Definition StructArrayTelemetry.hpp:94
bool Set(std::span< const T > value)
Definition StructArrayTelemetry.hpp:108
void Enable()
Definition StructArrayTelemetry.hpp:156
void Display(bool state)
Definition StructArrayTelemetry.hpp:164
void SetupNetworkTables(std::shared_ptr< wpi::nt::NetworkTable > dataTable, std::shared_ptr< wpi::nt::NetworkTable > tuningTable)
Definition StructArrayTelemetry.hpp:62
Definition SwerveDrive.hpp:864