Update LiveWindow to provide continuous telemetry. (#771)

LiveWindow.updateValues() is now called from IterativeRobotBase on every
loop iteration.  Telemetry for all WPILib classes is enabled by default;
it can be disabled for specific classes using LiveWindow.disableTelemetry(),
or all telemetry can be disabled using LiveWindow.disableAllTelemetry().

This necessitated changing the hook methodology into other classes to
be more property-based rather than each class providing multiple functions.
This had the benefit of reducing boilerplate and increasing consistency.

- Remove NamedSendable, add name to Sendable.

- Provide SendableBase abstract class.

- Deprecate LiveWindow addSensor/addActuator interfaces.

- Add LiveWindow support to drive classes.

- Add addChild() helper functions to Subsystem.

- Fix inheritance hierarchy.  Now only sensors inherit from SensorBase.
  Other devices inherit from some combination of SendableBase, ErrorBase, or
  nothing.
This commit is contained in:
Peter Johnson
2017-12-04 23:28:33 -08:00
committed by GitHub
parent 3befc7015b
commit f9bece2ffb
213 changed files with 3704 additions and 3758 deletions

View File

@@ -1,29 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2012-2017 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 <string>
#include "SmartDashboard/Sendable.h"
namespace frc {
/**
* The interface for sendable objects that gives the sendable a default name in
* the Smart Dashboard.
*/
class NamedSendable : public Sendable {
public:
/**
* @return The name of the subtable of SmartDashboard that the Sendable object
* will use
*/
virtual std::string GetName() const = 0;
};
} // namespace frc

View File

@@ -7,27 +7,63 @@
#pragma once
#include <memory>
#include <string>
#include "networktables/NetworkTable.h"
#include <llvm/Twine.h>
namespace frc {
class SendableBuilder;
class Sendable {
public:
/**
* Initializes a table for this sendable object.
*
* @param subtable The table to put the values in.
*/
virtual void InitTable(std::shared_ptr<nt::NetworkTable> subtable) = 0;
virtual ~Sendable() = default;
/**
* @return The string representation of the named data type that will be used
* by the smart dashboard for this sendable
* Gets the name of this Sendable object.
*
* @return Name
*/
virtual std::string GetSmartDashboardType() const = 0;
virtual std::string GetName() const = 0;
/**
* Sets the name of this Sendable object.
*
* @param name name
*/
virtual void SetName(const llvm::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 llvm::Twine& subsystem, const llvm::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 llvm::Twine& subsystem) = 0;
/**
* Initializes this Sendable object.
*
* @param builder sendable builder
*/
virtual void InitSendable(SendableBuilder& builder) = 0;
};
} // namespace frc

View File

@@ -0,0 +1,44 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017 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 <support/mutex.h>
#include "Sendable.h"
namespace frc {
class SendableBase : public Sendable {
public:
explicit SendableBase(bool addLiveWindow = true);
~SendableBase() override;
using Sendable::SetName;
std::string GetName() const final;
void SetName(const llvm::Twine& name) final;
std::string GetSubsystem() const final;
void SetSubsystem(const llvm::Twine& subsystem) final;
protected:
void AddChild(std::shared_ptr<Sendable> child);
void AddChild(void* child);
void SetName(const llvm::Twine& moduleType, int channel);
void SetName(const llvm::Twine& moduleType, int moduleNumber, int channel);
private:
mutable wpi::mutex m_mutex;
std::string m_name;
std::string m_subsystem = "Ungrouped";
};
} // namespace frc

View File

@@ -0,0 +1,217 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017 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 <functional>
#include <memory>
#include <string>
#include <vector>
#include <llvm/ArrayRef.h>
#include <llvm/SmallVector.h>
#include <llvm/Twine.h>
#include "networktables/NetworkTableEntry.h"
#include "networktables/NetworkTableValue.h"
namespace frc {
class SendableBuilder {
public:
virtual ~SendableBuilder() = default;
/**
* Set the string representation of the named data type that will be used
* by the smart dashboard for this sendable.
*
* @param type data type
*/
virtual void SetSmartDashboardType(const llvm::Twine& type) = 0;
/**
* Set the function that should be called to set the Sendable into a safe
* state. This is called when entering and exiting Live Window mode.
*
* @param func function
*/
virtual void SetSafeState(std::function<void()> func) = 0;
/**
* Set the function that should be called to update the network table
* for things other than properties. Note this function is not passed
* the network table object; instead it should use the entry handles
* returned by GetEntry().
*
* @param func function
*/
virtual void SetUpdateTable(std::function<void()> func) = 0;
/**
* Add a property without getters or setters. This can be used to get
* entry handles for the function called by SetUpdateTable().
*
* @param key property name
* @return Network table entry
*/
virtual nt::NetworkTableEntry GetEntry(const llvm::Twine& key) = 0;
/**
* Add a boolean property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddBooleanProperty(const llvm::Twine& key,
std::function<bool()> getter,
std::function<void(bool)> setter) = 0;
/**
* Add a double property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddDoubleProperty(const llvm::Twine& key,
std::function<double()> getter,
std::function<void(double)> setter) = 0;
/**
* Add a string property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddStringProperty(
const llvm::Twine& key, std::function<std::string()> getter,
std::function<void(llvm::StringRef)> setter) = 0;
/**
* Add a boolean array property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddBooleanArrayProperty(
const llvm::Twine& key, std::function<std::vector<int>()> getter,
std::function<void(llvm::ArrayRef<int>)> setter) = 0;
/**
* Add a double array property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddDoubleArrayProperty(
const llvm::Twine& key, std::function<std::vector<double>()> getter,
std::function<void(llvm::ArrayRef<double>)> setter) = 0;
/**
* Add a string array property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddStringArrayProperty(
const llvm::Twine& key, std::function<std::vector<std::string>()> getter,
std::function<void(llvm::ArrayRef<std::string>)> setter) = 0;
/**
* Add a raw property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddRawProperty(const llvm::Twine& key,
std::function<std::string()> getter,
std::function<void(llvm::StringRef)> setter) = 0;
/**
* Add a NetworkTableValue property.
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddValueProperty(
const llvm::Twine& key,
std::function<std::shared_ptr<nt::Value>()> getter,
std::function<void(std::shared_ptr<nt::Value>)> setter) = 0;
/**
* Add a string property (SmallString form).
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddSmallStringProperty(
const llvm::Twine& key,
std::function<llvm::StringRef(llvm::SmallVectorImpl<char>& buf)> getter,
std::function<void(llvm::StringRef)> setter) = 0;
/**
* Add a boolean array property (SmallVector form).
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddSmallBooleanArrayProperty(
const llvm::Twine& key,
std::function<llvm::ArrayRef<int>(llvm::SmallVectorImpl<int>& buf)>
getter,
std::function<void(llvm::ArrayRef<int>)> setter) = 0;
/**
* Add a double array property (SmallVector form).
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddSmallDoubleArrayProperty(
const llvm::Twine& key,
std::function<llvm::ArrayRef<double>(llvm::SmallVectorImpl<double>& buf)>
getter,
std::function<void(llvm::ArrayRef<double>)> setter) = 0;
/**
* Add a string array property (SmallVector form).
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddSmallStringArrayProperty(
const llvm::Twine& key,
std::function<
llvm::ArrayRef<std::string>(llvm::SmallVectorImpl<std::string>& buf)>
getter,
std::function<void(llvm::ArrayRef<std::string>)> setter) = 0;
/**
* Add a raw property (SmallVector form).
*
* @param key property name
* @param getter getter function (returns current value)
* @param setter setter function (sets new value)
*/
virtual void AddSmallRawProperty(
const llvm::Twine& key,
std::function<llvm::StringRef(llvm::SmallVectorImpl<char>& buf)> getter,
std::function<void(llvm::StringRef)> setter) = 0;
};
} // namespace frc

View File

@@ -0,0 +1,182 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017 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 <functional>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <llvm/ArrayRef.h>
#include <llvm/SmallVector.h>
#include <llvm/Twine.h>
#include "SendableBuilder.h"
#include "networktables/NetworkTable.h"
#include "networktables/NetworkTableEntry.h"
#include "networktables/NetworkTableValue.h"
namespace frc {
class SendableBuilderImpl : public SendableBuilder {
public:
SendableBuilderImpl() = default;
SendableBuilderImpl(const SendableBuilderImpl&) = delete;
SendableBuilderImpl(SendableBuilderImpl&& other) = default;
SendableBuilderImpl& operator=(const SendableBuilderImpl&) = delete;
SendableBuilderImpl& operator=(SendableBuilderImpl&& other) = default;
~SendableBuilderImpl() override = default;
/**
* Set the network table. Must be called prior to any Add* functions being
* called.
* @param table Network table
*/
void SetTable(std::shared_ptr<nt::NetworkTable> table);
/**
* Get the network table.
* @return The network table
*/
std::shared_ptr<nt::NetworkTable> GetTable();
/**
* Update the network table values by calling the getters for all properties.
*/
void UpdateTable();
/**
* Start LiveWindow mode by hooking the setters for all properties.
*/
void StartLiveWindowMode();
/**
* Stop LiveWindow mode by unhooking the setters for all properties.
*/
void StopLiveWindowMode();
void SetSmartDashboardType(const llvm::Twine& type) override;
void SetSafeState(std::function<void()> func) override;
void SetUpdateTable(std::function<void()> func) override;
nt::NetworkTableEntry GetEntry(const llvm::Twine& key) override;
void AddBooleanProperty(const llvm::Twine& key, std::function<bool()> getter,
std::function<void(bool)> setter) override;
void AddDoubleProperty(const llvm::Twine& key, std::function<double()> getter,
std::function<void(double)> setter) override;
void AddStringProperty(const llvm::Twine& key,
std::function<std::string()> getter,
std::function<void(llvm::StringRef)> setter) override;
void AddBooleanArrayProperty(
const llvm::Twine& key, std::function<std::vector<int>()> getter,
std::function<void(llvm::ArrayRef<int>)> setter) override;
void AddDoubleArrayProperty(
const llvm::Twine& key, std::function<std::vector<double>()> getter,
std::function<void(llvm::ArrayRef<double>)> setter) override;
void AddStringArrayProperty(
const llvm::Twine& key, std::function<std::vector<std::string>()> getter,
std::function<void(llvm::ArrayRef<std::string>)> setter) override;
void AddRawProperty(const llvm::Twine& key,
std::function<std::string()> getter,
std::function<void(llvm::StringRef)> setter) override;
void AddValueProperty(
const llvm::Twine& key,
std::function<std::shared_ptr<nt::Value>()> getter,
std::function<void(std::shared_ptr<nt::Value>)> setter) override;
void AddSmallStringProperty(
const llvm::Twine& key,
std::function<llvm::StringRef(llvm::SmallVectorImpl<char>& buf)> getter,
std::function<void(llvm::StringRef)> setter) override;
void AddSmallBooleanArrayProperty(
const llvm::Twine& key,
std::function<llvm::ArrayRef<int>(llvm::SmallVectorImpl<int>& buf)>
getter,
std::function<void(llvm::ArrayRef<int>)> setter) override;
void AddSmallDoubleArrayProperty(
const llvm::Twine& key,
std::function<llvm::ArrayRef<double>(llvm::SmallVectorImpl<double>& buf)>
getter,
std::function<void(llvm::ArrayRef<double>)> setter) override;
void AddSmallStringArrayProperty(
const llvm::Twine& key,
std::function<
llvm::ArrayRef<std::string>(llvm::SmallVectorImpl<std::string>& buf)>
getter,
std::function<void(llvm::ArrayRef<std::string>)> setter) override;
void AddSmallRawProperty(
const llvm::Twine& key,
std::function<llvm::StringRef(llvm::SmallVectorImpl<char>& buf)> getter,
std::function<void(llvm::StringRef)> setter) override;
private:
struct Property {
Property(nt::NetworkTable& table, const llvm::Twine& key)
: entry(table.GetEntry(key)) {}
Property(const Property&) = delete;
Property& operator=(const Property&) = delete;
Property(Property&& other) noexcept
: entry(other.entry),
listener(other.listener),
update(std::move(other.update)),
createListener(std::move(other.createListener)) {
other.entry = nt::NetworkTableEntry();
other.listener = 0;
}
Property& operator=(Property&& other) noexcept {
entry = other.entry;
listener = other.listener;
other.entry = nt::NetworkTableEntry();
other.listener = 0;
update = std::move(other.update);
createListener = std::move(other.createListener);
return *this;
}
~Property() { StopListener(); }
void StartListener() {
if (entry && listener == 0 && createListener)
listener = createListener(entry);
}
void StopListener() {
if (entry && listener != 0) {
entry.RemoveListener(listener);
listener = 0;
}
}
nt::NetworkTableEntry entry;
NT_EntryListener listener = 0;
std::function<void(nt::NetworkTableEntry entry, uint64_t time)> update;
std::function<NT_EntryListener(nt::NetworkTableEntry entry)> createListener;
};
std::vector<Property> m_properties;
std::function<void()> m_safeState;
std::function<void()> m_updateTable;
std::shared_ptr<nt::NetworkTable> m_table;
};
} // namespace frc

View File

@@ -8,14 +8,11 @@
#pragma once
#include <memory>
#include <string>
#include <llvm/StringMap.h>
#include <llvm/StringRef.h>
#include "SmartDashboard/SendableChooserBase.h"
#include "networktables/NetworkTable.h"
#include "networktables/NetworkTableEntry.h"
namespace frc {
@@ -35,7 +32,6 @@ namespace frc {
template <class T>
class SendableChooser : public SendableChooserBase {
llvm::StringMap<T> m_choices;
nt::NetworkTableEntry m_selectedEntry;
template <class U>
static U _unwrap_smart_ptr(const U& value);
@@ -47,14 +43,14 @@ class SendableChooser : public SendableChooserBase {
static std::weak_ptr<U> _unwrap_smart_ptr(const std::shared_ptr<U>& value);
public:
virtual ~SendableChooser() = default;
~SendableChooser() override = default;
void AddObject(llvm::StringRef name, T object);
void AddDefault(llvm::StringRef name, T object);
auto GetSelected() -> decltype(_unwrap_smart_ptr(m_choices[""]));
void InitTable(std::shared_ptr<nt::NetworkTable> subtable) override;
void InitSendable(SendableBuilder& builder) override;
};
} // namespace frc

View File

@@ -13,6 +13,10 @@
#include <utility>
#include <vector>
#include <llvm/StringRef.h>
#include "SendableBuilder.h"
namespace frc {
/**
@@ -58,8 +62,11 @@ void SendableChooser<T>::AddDefault(llvm::StringRef name, T object) {
template <class T>
auto SendableChooser<T>::GetSelected()
-> decltype(_unwrap_smart_ptr(m_choices[""])) {
std::string selected = m_selectedEntry.GetString(m_defaultChoice);
if (selected == "") {
llvm::StringRef selected = m_defaultChoice;
if (m_selectedEntry) {
selected = m_selectedEntry.GetString(m_defaultChoice);
}
if (selected.empty()) {
return decltype(_unwrap_smart_ptr(m_choices[""])){};
} else {
return _unwrap_smart_ptr(m_choices[selected]);
@@ -67,21 +74,29 @@ auto SendableChooser<T>::GetSelected()
}
template <class T>
void SendableChooser<T>::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
std::vector<std::string> keys;
if (subtable) {
m_selectedEntry = subtable->GetEntry(kSelected);
for (const auto& choice : m_choices) {
keys.push_back(choice.first());
}
void SendableChooser<T>::InitSendable(SendableBuilder& builder) {
builder.SetSmartDashboardType("String Chooser");
builder.AddStringArrayProperty(kOptions,
[=]() {
std::vector<std::string> keys;
for (const auto& choice : m_choices) {
keys.push_back(choice.first());
}
// Unlike std::map, llvm::StringMap elements are not sorted
std::sort(keys.begin(), keys.end());
// Unlike std::map, llvm::StringMap elements
// are not sorted
std::sort(keys.begin(), keys.end());
subtable->GetEntry(kOptions).SetValue(
nt::Value::MakeStringArray(std::move(keys)));
subtable->GetEntry(kDefault).SetString(m_defaultChoice);
}
return keys;
},
nullptr);
builder.AddSmallStringProperty(
kDefault,
[=](const llvm::SmallVectorImpl<char>&) -> llvm::StringRef {
return m_defaultChoice;
},
nullptr);
m_selectedEntry = builder.GetEntry(kSelected);
}
template <class T>

View File

@@ -7,11 +7,10 @@
#pragma once
#include <memory>
#include <string>
#include "SmartDashboard/Sendable.h"
#include "networktables/NetworkTable.h"
#include "SmartDashboard/SendableBase.h"
#include "networktables/NetworkTableEntry.h"
namespace frc {
@@ -21,11 +20,9 @@ namespace frc {
* It contains static, non-templated variables to avoid their duplication in the
* template class.
*/
class SendableChooserBase : public Sendable {
class SendableChooserBase : public SendableBase {
public:
virtual ~SendableChooserBase() = default;
std::string GetSmartDashboardType() const override;
~SendableChooserBase() override = default;
protected:
static const char* kDefault;
@@ -33,6 +30,7 @@ class SendableChooserBase : public Sendable {
static const char* kSelected;
std::string m_defaultChoice;
nt::NetworkTableEntry m_selectedEntry;
};
} // namespace frc

View File

@@ -16,7 +16,6 @@
namespace frc {
class NamedSendable;
class Sendable;
class SmartDashboard : public SensorBase {
@@ -38,7 +37,7 @@ class SmartDashboard : public SensorBase {
static void Delete(llvm::StringRef key);
static void PutData(llvm::StringRef key, Sendable* data);
static void PutData(NamedSendable* value);
static void PutData(Sendable* value);
static Sendable* GetData(llvm::StringRef keyName);
static bool PutBoolean(llvm::StringRef keyName, bool value);