Elastic Basics

Introduction

Elastic is a web-based dashboard for FRC robots, offering real-time data visualization and control. It connects via NetworkTables and runs in a browser, allowing access from multiple devices simultaneously.

Resources:
WPILib Documentation
Official Elastic Documentation

Features

Elastic allows you to:

  • View sensor data and robot state in real-time.
  • Create custom layouts with drag-and-drop widgets.
  • Monitor motor stats (speed, current, temp).
  • Visualize robot pose on a 2D field.
  • Plot data with interactive graphs.
  • Access from multiple devices.
  • Create responsive layouts.

Installation & Launch

Installation: Elastic is included with WPILib. Ensure you have the latest version from the WPILib releases page.

Launch:
1. Run your robot code.
2. Open a browser on a connected device.
3. Navigate to https://gold872.github.io/elastic-dashboard/ or use the desktop app.

Configuration: Ensure your team number is set in the project settings for correct IP resolution.

Interface

Components:
- Canvas: Main area for widgets.
- Library: Available widgets.
- Configuration: Widget settings.
- Toolbar: Layout tools.

Widgets:
- Basic: Numbers, text, booleans.
- Charts: Line/bar charts, gauges.
- Field: 2D robot visualization.
- Controls: Buttons, sliders, inputs.
- Media: Camera streams.

Displaying Data

Elastic uses NetworkTables. The easiest method is via the SmartDashboard compatibility layer.

Sending Data (SmartDashboard)

package frc.robot;

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;

public class Robot extends TimedRobot {
    private double motorSpeed = 0.5;
    private String status = "Running";
    
    @Override
    public void robotPeriodic() {
        // Send data to SmartDashboard (visible in Elastic)
        SmartDashboard.putNumber("Motor Speed", motorSpeed);
        SmartDashboard.putString("Robot Status", status);
        SmartDashboard.putBoolean("Enabled", true);
    }
}

Widgets

Adding: Click the "Add Widget" (+) button, find your data in the NetworkTables list, and drag it to the grid.

Editing: Right-click a widget to edit properties (title, type, settings) or remove it.

Cameras: Start automatic capture in robotInit() (CameraServer.startAutomaticCapture();), then add the stream from the CameraPublisher table.

Interactive Controls

Create buttons, sliders, or inputs in Elastic to control the robot.

Reading Values: Use SmartDashboard.get methods.
- getNumber("key", default)
- getString("key", default)
- getBoolean("key", default)

Reading Data

package frc.robot;

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;

public class Robot extends TimedRobot {
    @Override
    public void robotPeriodic() {
        // Read values from SmartDashboard (set by Elastic widgets)
        // Second parameter is default value if key doesn't exist
        double speed = SmartDashboard.getNumber("Target Speed", 0.0);
        boolean enable = SmartDashboard.getBoolean("Enable", false);
        
        if (enable) {
            setMotorSpeed(speed);
        }
    }
    
    private void setMotorSpeed(double speed) {
        // Motor control logic here
    }
}

Arm Example

Complete arm control with Elastic dashboard:
package frc.robot;

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import com.ctre.phoenix6.hardware.TalonFX;
import com.ctre.phoenix6.controls.DutyCycleOut;

public class Robot extends TimedRobot {
    // Arm motor on CAN ID 3
    private final TalonFX m_motor = new TalonFX(3);
    private final DutyCycleOut m_output = new DutyCycleOut(0);
    
    @Override
    public void robotInit() {
        // Initialize dashboard value (creates widget in Elastic)
        SmartDashboard.putNumber("Arm Target", 0.0);
    }
    
    @Override
    public void robotPeriodic() {
        // Read target from dashboard (set by user in Elastic)
        double target = SmartDashboard.getNumber("Arm Target", 0.0);
        
        // Send current position to dashboard (displayed in Elastic)
        SmartDashboard.putNumber("Arm Pos", m_motor.getPosition().getValueAsDouble());
        
        // Control logic here (e.g., PID to reach target)
        // For now, just set motor to target value
        m_motor.setControl(m_output.withOutput(target));
    }
}

Advanced Features

Charts: Visualize data over time (e.g., PID tuning).
Field: 2D field view (requires odometry).
Command Widgets: Monitor command and subsystem states.
Custom: Elastic supports custom widgets.

Field Visualization

Setup:
1. Add a Field widget.
2. Configure the field image.
3. Send Pose2d data via Field2d object.

Field Pose Example

package frc.robot;

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.smartdashboard.Field2d;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.math.geometry.Pose2d;

public class Robot extends TimedRobot {
    // Field visualization object
    private final Field2d m_field = new Field2d();
    
    @Override
    public void robotInit() {
        // Add field widget to SmartDashboard (visible in Elastic)
        SmartDashboard.putData("Field", m_field);
    }
    
    @Override
    public void robotPeriodic() {
        // Update robot pose on field visualization
        Pose2d currentPose = getOdometryPose();
        m_field.setRobotPose(currentPose);
    }
    
    private Pose2d getOdometryPose() {
        // Return current robot pose from odometry
        return new Pose2d(); // Placeholder
    }
}

Considerations

Multi-Device: Multiple browsers can connect. Useful for separate driver/operator views.
Performance: Manage bandwidth. Update non-critical data less frequently (5-20 Hz).

Resources

Open full interactive app