Elastic Dashboard

repository·main·Indexed 40 days ago

https://github.com/gold872/elastic_dashboard

A modern, lightweight dashboard application for FRC (FIRST Robotics Competition) teams to monitor robot data and camera streams. It features customizable color schemes, optimized camera streams, and support for NetworkTables 4 (NT4) type parsing and struct schemas.

Tokens
7.6K
Snippets
22
Records
33
Agent score
100%

What's inside Elastic Dashboard

  1. Overview of Elastic Dashboard

    main

    Elastic is a simple and modern dashboard designed for FRC (FIRST Robotics Competition). It is optimized for use as a competition driver dashboard (behind the glass) or for testing purposes.

    Key features include:

    • Customizable color schemes: Over 20 variants available.
    • Subscription sharing: Reduces bandwidth consumption by sharing subscriptions.
    • Optimized camera streams: Automatically deactivates streams when they are not in use.
    • Automatic height resizing: Adjusts to the FRC Driver Station height.
  2. Download and Run Elastic Dashboard

    main

    You can use Elastic Dashboard as a standalone application or directly in your web browser.

    Standalone Installation

    Download the latest release files for your operating system from the GitHub releases page. Supported platforms include:

    • Windows
    • MacOS
    • Linux

    Web Version

    To try the dashboard immediately without installation, use the hosted web version.

    https://gold872.github.io/elastic_dashboard/
  3. Understand the Field class properties and lifecycle

    main

    A Field object represents a specific game's layout, including its physical dimensions, coordinate system, and visual representation.

    Key Properties

    • game: The name of the game.
    • program: Indicates if the field is for 'FRC' or 'FTC'.
    • coordinateSystem: The CoordinateSystem used for this field.
    • fieldWidthMeters / fieldHeightMeters: Physical dimensions of the field.
    • fieldImage: The Flutter Image widget used to render the field.
    • pixelsPerMeterHorizontal / pixelsPerMeterVertical: Scaling factors used to convert physical distances to pixel offsets.
    • topLeftCorner / bottomRightCorner: The pixel offsets defining the field boundaries.

    Lifecycle and Memory Management

    Fields use an instanceCount to track how many parts of the application are currently using them.

    • Loading: loadFieldImage() is called when the first instance is requested. This resolves the asset image and sets fieldImageLoaded to true once the dimensions are known.
    • Disposing: Call dispose() to decrement the instanceCount. When the count reaches zero, the field image is evicted from the imageCache to free up memory.
  4. Define NTStruct schema syntax

    main

    Schemas are defined as strings where fields are separated by semicolons (;).

    Field Declarations

    • Standard types: type fieldName; (e.g., int32 myInt;)
    • Bit-fields: type fieldName:bitWidth; (e.g., bool myFlag:1; defines a 1-bit boolean field)
    • Arrays: type fieldName[length]; (e.g., int16 myBuffer[10];)
    • Enums: enum {Key=Value, ...} type fieldName; (e.g., enum {Red=0, Blue=1} color;)
    • Sub-structs: struct TypeName fieldName; (where TypeName is a previously registered schema)

    Supported Types

    • Integers: int8, int16, int32, int64, uint8, uint16, uint32, uint64, char
    • Floating Point: float, float32, double, float64
    • Other: bool, struct
  5. Configure CustomAppBar window behavior

    main

    The CustomAppBar behavior is influenced by both its own properties and the global Settings class:

    1. Closing the Window:

      • If you provide an onWindowClose callback, that function is executed when the close button is clicked.
      • If onWindowClose is null, the widget calls windowManager.close().
    2. Maximizing/Unmaximizing:

      • The maximize button and double-tap on the drag area only function if Settings.isWindowMaximizable is true.
    3. Window Dragging:

      • The ability to drag the window by interacting with the title area is controlled by Settings.isWindowDraggable.
  6. Understand MjpegController stream lifecycle states

    main

    The MjpegController transitions through several states defined by the StreamCycleState enum. Monitoring cycleState allows you to react to connection changes.

    StateDescription
    idleNo active stream and no pending connections.
    connectingAttempting to establish an HTTP connection to the current stream URL.
    streamingSuccessfully connected and receiving JPEG frames.
    reconnectingThe current stream failed or ended; the controller is attempting to switch to the next URL in the streams list.
    disposedThe controller has been shut down and cannot be reused.
  7. Understand NT4DataType and NT4TypeModifier

    main

    NT4 data is categorized by its underlying data format and its structural modifier.

    NT4DataType

    Defines the primitive or serialized format:

    • boolean, int32, float32, float64, string, json (Viewable types)
    • raw, rpc, msgpack, protobuf, structschema, unknown (Binary/Non-viewable types)

    Helper Properties:

    • isViewable: Returns true if the type can be easily displayed in a UI widget (primitives).
    • isNumber: Returns true for int32, float32, or float64.
    • isBinary: Returns true for non-primitive/serialized types like raw, protobuf, etc.

    NT4TypeModifier

    Defines how the data is structured:

    • normal: A single value.
    • array: A list of primitive values (e.g., int[]).
    • struct: A complex object defined by a schema (e.g., struct:MyData).
    • structarray: A list of complex objects (e.g., struct:MyData[]).
  8. Use the NetworkAlerts widget to display network alerts

    main

    The NetworkAlerts widget is a specialized NTWidget designed to display a categorized list of network alerts (Errors, Warnings, and Infos) in a scrollable list. It relies on a NetworkAlertsModel to manage subscriptions to specific network topics.

    Data Structure

    The widget consumes data from three distinct sub-topics derived from the base topic:

    • errors: {topic}/errors (displayed with a red Icons.cancel icon)
    • warnings: {topic}/warnings (displayed with a yellow Icons.warning icon)
    • infos: {topic}/infos (displayed with a green Icons.info icon)

    Implementation Details

    • Data Type: The widget expects the subscription values to be lists of strings (List<String>). It uses tryCast<List<Object?>>() to safely handle incoming data and filters for String types.
    • Reactivity: The widget uses a ListenableBuilder that listens to all active NT4Subscription objects managed by the NetworkAlertsModel. When any of the three subscriptions receive new data, the UI updates automatically.
    • Layout: Alerts are rendered in a single ListView.builder in the following priority order: Errors, then Warnings, then Infos.
    // To use the widget in a Flutter build method:
    NetworkAlerts()
  9. Display an MJPEG video stream with the Mjpeg widget

    main

    Use the Mjpeg widget to render a video stream from an MJPEG source. It requires an MjpegController to manage the stream lifecycle and connection. You can customize the appearance using fit, width, height, and quarterTurns (for rotation). The widget also supports custom loading and error UI builders.

    Key Properties

    • controller: An MjpegController instance.
    • fit: BoxFit for how the image fills the container.
    • quarterTurns: Number of 90-degree turns to rotate the video.
    • loading: A builder function to show a custom widget while connecting.
    • error: A builder function to show a custom widget when a stream error occurs.
    Mjpeg(
      controller: myMjpegController,
      fit: BoxFit.cover,
      quarterTurns: 1,
      loading: (context) => CircularProgressIndicator(),
      error: (context, error, stack) => Text('Error: $error'),
    )
  10. Convert external coordinate systems to internal mapping using CoordinateSystemConverter.convertToInternal

    main

    Use CoordinateSystemConverter.convertToInternal to transform coordinates from various external standards (like WPILib or FTC) into the project's internal coordinate system.

    Internal Coordinate System Definition:

    • Origin: Center of the field.
    • +X direction: Towards the Blue alliance (right side of the image).
    • +Y direction: Towards the scoring table (top of the image).

    Supported Coordinate Systems:

    • CoordinateSystem.wallBlue: Standard WPILib pre-2027 (Origin at blue alliance corner, +X left, +Y bottom).
    • CoordinateSystem.centerRotated: Standard FTC pre-2028 (Origin at center, +X along red wall towards bottom, +Y right).
    • CoordinateSystem.center: Standard WPILib 2027+ (Origin at center, +X towards blue alliance wall, +Y towards scoring table).
    • CoordinateSystem.unknown: Defaults to center mapping.
    // Example conversion
    final (double x, double y, double angle) internalCoords = CoordinateSystemConverter.convertToInternal(
      CoordinateSystem.wallBlue,
      rawX,
      rawY,
      rawAngleRadians,
      field,
    );
  11. Implement a custom MjpegPreprocessor

    main

    If your MJPEG stream requires specific byte-level manipulation before being rendered, implement the MjpegPreprocessor class. The process method receives the raw frame bytes and should return the processed List<int> to be used by the Image.memory widget.

    class MyCustomPreprocessor extends MjpegPreprocessor {
      @override
      List<int>? process(List<int> frame) {
        // Perform custom byte manipulation here
        return frame;
      }
    }
    
    // Usage
    final controller = MjpegController(
      streams: ['...'],
      preprocessor: MyCustomPreprocessor(),
    );