62 m_liveTuningPath{
"Tuning/SwerveInputStream/" + std::string{name} +
"/Live Tuning"} {
63 auto instance = wpi::nt::NetworkTableInstance::GetDefault();
64 auto dataTable = instance.GetTable(
"SwerveInputStream")->GetSubTable(name);
65 m_modePublisher = dataTable->GetStringTopic(
"mode").Publish();
67 if (verbosity == TelemetryVerbosity::MEDIUM || verbosity == TelemetryVerbosity::HIGH) {
68 PublishConfig(*dataTable);
70 if (verbosity == TelemetryVerbosity::HIGH) {
72 *instance.GetTable(
"Tuning")->GetSubTable(
"SwerveInputStream")->GetSubTable(name));
74 m_liveTuningCommand.emplace(
77 wpi::tunables::Publish(m_liveTuningPath, *m_liveTuningCommand->get());
87 if (m_liveTuningCommand) {
88 m_liveTuningCommand->Cancel();
89 wpi::tunables::Remove(m_liveTuningPath);
98 m_modePublisher.Set(m_stream->GetCurrentModeName());
99 for (
auto& publish : m_configPublishers) {
109 for (
auto& value : m_doubles) {
112 for (
auto& value : m_booleans) {
124 if (!m_liveTuningCommand) {
127 return std::ref(*m_liveTuningCommand->get());
132 template <
typename T,
typename Entry>
144 TunableValue(wpi::nt::NetworkTable& table, std::string_view key, std::function<T()> getter,
145 std::function<
void(T)> setter,
146 std::function<
bool(T)> valid = [](T) {
return true; })
147 : m_getter{std::move(getter)},
148 m_setter{std::move(setter)},
149 m_valid{std::move(valid)},
150 m_lastValue{m_getter()},
151 m_entry{MakeEntry(table, key, m_lastValue)} {
152 m_entry.Set(m_lastValue);
157 T published = m_entry.Get();
158 if (published != m_lastValue && m_valid(published)) {
161 T current = m_getter();
162 if (current != published) {
163 m_entry.Set(current);
165 m_lastValue = current;
169 static Entry MakeEntry(wpi::nt::NetworkTable& table, std::string_view key, T defaultValue) {
170 if constexpr (std::is_same_v<T, bool>) {
171 return table.GetBooleanTopic(key).GetEntry(defaultValue);
173 return table.GetDoubleTopic(key).GetEntry(defaultValue);
177 std::function<T()> m_getter;
178 std::function<void(T)> m_setter;
179 std::function<bool(T)> m_valid;
185 void PublishConfig(wpi::nt::NetworkTable& table) {
186 PublishDouble(table,
"deadband", [
this] {
return m_stream->GetAxisDeadband(); });
187 PublishDouble(table,
"translationScale", [
this] {
return m_stream->GetTranslationAxisScale(); });
188 PublishDouble(table,
"rotationScale", [
this] {
return m_stream->GetOmegaAxisScale(); });
189 PublishDouble(table,
"maxLinearVelocity",
190 [
this] {
return m_stream->GetMaximumChassisLinearVelocity().value(); });
191 PublishDouble(table,
"maxAngularVelocity",
192 [
this] {
return m_stream->GetMaximumChassisAngularVelocity().value(); });
193 PublishBoolean(table,
"translationCube", [
this] {
return m_stream->IsTranslationCubeEnabled(); });
194 PublishBoolean(table,
"rotationCube", [
this] {
return m_stream->IsOmegaCubeEnabled(); });
195 PublishBoolean(table,
"allianceRelative",
196 [
this] {
return m_stream->IsAllianceRelativeEnabled(); });
197 PublishBoolean(table,
"robotRelative", [
this] {
return m_stream->IsRobotRelativeEnabled(); });
200 void PublishDouble(wpi::nt::NetworkTable& table, std::string_view key,
201 std::function<
double()> value) {
203 std::make_shared<wpi::nt::DoublePublisher>(table.GetDoubleTopic(key).Publish());
204 m_configPublishers.emplace_back(
205 [publisher, value = std::move(value)] { publisher->Set(value()); });
208 void PublishBoolean(wpi::nt::NetworkTable& table, std::string_view key,
209 std::function<
bool()> value) {
211 std::make_shared<wpi::nt::BooleanPublisher>(table.GetBooleanTopic(key).Publish());
212 m_configPublishers.emplace_back(
213 [publisher, value = std::move(value)] { publisher->Set(value()); });
216 void AddTunableValues(wpi::nt::NetworkTable& table) {
217 m_doubles.emplace_back(
218 table,
"deadband", [
this] {
return m_stream->GetAxisDeadband(); },
219 [
this](
double value) { m_stream->SetAxisDeadband(value); },
220 [](
double value) {
return value >= 0.0 && value < 1.0; });
221 m_doubles.emplace_back(
222 table,
"translationScale", [
this] {
return m_stream->GetTranslationAxisScale(); },
223 [
this](
double value) { m_stream->SetTranslationAxisScale(value); },
224 [](
double value) {
return value > 0.0 && value <= 1.0; });
225 m_doubles.emplace_back(
226 table,
"rotationScale", [
this] {
return m_stream->GetOmegaAxisScale(); },
227 [
this](
double value) { m_stream->SetOmegaAxisScale(value); },
228 [](
double value) {
return value > 0.0 && value <= 1.0; });
229 m_doubles.emplace_back(
230 table,
"maxLinearVelocity",
231 [
this] {
return m_stream->GetMaximumChassisLinearVelocity().value(); },
232 [
this](
double value) {
233 m_stream->SetMaximumChassisLinearVelocity(wpi::units::meters_per_second_t{value});
235 [](
double value) {
return value > 0.0 && std::isfinite(value); });
236 m_doubles.emplace_back(
237 table,
"maxAngularVelocity",
238 [
this] {
return m_stream->GetMaximumChassisAngularVelocity().value(); },
239 [
this](
double value) {
240 m_stream->SetMaximumChassisAngularVelocity(wpi::units::radians_per_second_t{value});
242 [](
double value) {
return value > 0.0 && std::isfinite(value); });
243 m_booleans.emplace_back(
244 table,
"translationCube", [
this] {
return m_stream->IsTranslationCubeEnabled(); },
245 [
this](
bool value) { m_stream->SetTranslationCubeEnabled(value); });
246 m_booleans.emplace_back(
247 table,
"rotationCube", [
this] {
return m_stream->IsOmegaCubeEnabled(); },
248 [
this](
bool value) { m_stream->SetOmegaCubeEnabled(value); });
249 m_booleans.emplace_back(
250 table,
"allianceRelative", [
this] {
return m_stream->IsAllianceRelativeEnabled(); },
251 [
this](
bool value) { m_stream->SetAllianceRelativeEnabled(value); });
252 m_booleans.emplace_back(
253 table,
"robotRelative", [
this] {
return m_stream->IsRobotRelativeEnabled(); },
254 [
this](
bool value) { m_stream->SetRobotRelativeEnabled(value); });
257 SwerveInputStream<NumModules>* m_stream;
258 std::string m_liveTuningPath;
259 wpi::nt::StringPublisher m_modePublisher;
261 std::vector<std::function<void()>> m_configPublishers;
263 std::vector<TunableValue<double, wpi::nt::DoubleEntry>> m_doubles;
264 std::vector<TunableValue<bool, wpi::nt::BooleanEntry>> m_booleans;
266 std::optional<wpi::cmd::CommandPtr> m_liveTuningCommand;