Writing Your Own Sendable Classes
Desde que la interfaz «Sendable» solo tiene un método, escribir tus propias clases que implementen «Sendable» (y por lo tanto registren automáticamente valores en el panel de control y/o consuman valores del panel de control) es extremadamente fácil: simplemente proporciona una implementación para el método «initSendable» que se puede sobrescribir, en el cual los setters y getters de los campos de tu clase se enlazan declarativamente a los valores clave (sus nombres de visualización en el panel de control).
For example, here is the implementation of initSendable
from WPILib’s BangBangController
:
151 @Override
152 public void initSendable(SendableBuilder builder) {
153 builder.setSmartDashboardType("BangBangController");
154 builder.addDoubleProperty("tolerance", this::getTolerance, this::setTolerance);
155 builder.addDoubleProperty("setpoint", this::getSetpoint, this::setSetpoint);
156 builder.addDoubleProperty("measurement", this::getMeasurement, null);
157 builder.addDoubleProperty("error", this::getError, null);
158 builder.addBooleanProperty("atSetpoint", this::atSetpoint, null);
159 }
55void BangBangController::InitSendable(wpi::SendableBuilder& builder) {
56 builder.SetSmartDashboardType("BangBangController");
57 builder.AddDoubleProperty(
58 "tolerance", [this] { return GetTolerance(); },
59 [this](double tolerance) { SetTolerance(tolerance); });
60 builder.AddDoubleProperty(
61 "setpoint", [this] { return GetSetpoint(); },
62 [this](double setpoint) { SetSetpoint(setpoint); });
63 builder.AddDoubleProperty(
64 "measurement", [this] { return GetMeasurement(); }, nullptr);
65 builder.AddDoubleProperty(
66 "error", [this] { return GetError(); }, nullptr);
67 builder.AddBooleanProperty(
68 "atSetpoint", [this] { return AtSetpoint(); }, nullptr);
69}
To enable the automatic updating of values by WPILib «in the background», Sendable
data names are bound to getter and setter functions rather than specific data values. If a field that you wish to log has no defined setters and getters, they can be defined inline with a lambda expression.
The SendableBuilder Class
As seen above, the initSendable
method takes a single parameter, builder
, of type SendableBuilder
(Java, C++, Python
). This builder exposes methods that allow binding of getters and setters to dashboard names, as well as methods for safely ensuring that values consumed from the dashboard do not cause unsafe robot behavior.
Databinding with addProperty Methods
Como todo el código del panel de control de WPILib, los campos «Sendable» se transmiten en última instancia a través de NetworkTables, y por lo tanto, los métodos de enlace de datos proporcionados por «SendableBuilder» coinciden con los tipos de datos admitidos por NetworkTables.
boolean
:addBooleanProperty
boolean[]
:addBooleanArrayProperty
double
:addDoubleProperty
double[]
:addDoubleArrayProperty
string
:addStringProperty
string[]
:addStringArrayProperty
byte[]
:addRawProperty
Ensuring Safety with setSafeState and setActuator
Since Sendable
allows users to consume arbitrary values from the dashboard, it is possible for users to pipe dashboard controls directly to robot actuations. This is extremely unsafe if not done with care; dashboards are not a particularly good interface for controlling robot movement, and users generally do not expect the robot to move in response to a change on the dashboard.
To help users ensure safety when interfacing with dashboard values, SendableBuilder
exposes a setSafeState
method, which is called to place any Sendable
mechanism that actuates based on dashboard input into a safe state. Any potentially hazardous user-written Sendable
implementation should call setSafeState
with a suitable safe state implementation. For example, here is the implementation from the WPILib PWMMotorController
class:
120 @Override
121 public void initSendable(SendableBuilder builder) {
122 builder.setSmartDashboardType("Motor Controller");
123 builder.setActuator(true);
124 builder.setSafeState(this::disable);
125 builder.addDoubleProperty("Value", this::get, this::set);
126 }
56void PWMMotorController::InitSendable(wpi::SendableBuilder& builder) {
57 builder.SetSmartDashboardType("Motor Controller");
58 builder.SetActuator(true);
59 builder.SetSafeState([=, this] { Disable(); });
60 builder.AddDoubleProperty(
61 "Value", [=, this] { return Get(); },
62 [=, this](double value) { Set(value); });
Additionally, users may call builder.setActuator(true)
to mark any mechanism that might move as a result of Sendable
input as an actuator. Currently, this is used by Shuffleboard to disable actuator widgets when not in LiveWindow mode.