- FRC Game Manual
- FRC Game Q&A

# The Mechanism2d Widget

Glass supports displaying stick-figure representations of your robot’s mechanisms using the Mechanism2d widget. It supports combinations of ligaments that can rotate and / or extend or retract, such as arms and elevators and they can be combined for more complicated mechanisms. An instance of the `Mechanism2d` class should be created and populated, sent over NetworkTables, and updated periodically with the latest mechanism states in your robot code. It can also be used with the Physics Simulation to visualize and program your robot’s mechanisms before the robot is built.

## Creating and Configuring the Mechanism2d Instance

The `Mechanism2d` object is the “canvas” where the mechanism is drawn. The root node is where the mechanism is anchored to `Mechanism2d`. For a single jointed arm this would the pivot point. For an elevator, this would be where it’s attached to the robot’s base. To get a root node (represented by a `MechanismRoot2d` object), call `getRoot(name, x, y)` on the container `Mechanism2d` object. The name is used to name the root within NetworkTables, and should be unique, but otherwise isn’t important. The `x / y` coordinate system follows the same orientation as `Field2d` - `(0,0)` is bottom left.

In the examples below, an elevator is drawn, with a rotational wrist on top of the elevator. The full Mechanism2d example is available in Java / C++

JAVA

    43    // the main mechanism object
    44    Mechanism2d mech = new Mechanism2d(3, 3);
    45    // the mechanism root node
    46    MechanismRoot2d root = mech.getRoot("climber", 2, 0);

C++

    59  // the main mechanism object
    60  frc::Mechanism2d m_mech{3, 3};
    61  // the mechanism root node
    62  frc::MechanismRoot2d* m_root = m_mech.GetRoot("climber", 2, 0);

PYTHON

    32        # the main mechanism object
    33        self.mech = wpilib.Mechanism2d(3, 3)
    34        # the mechanism root node
    35        self.root = self.mech.getRoot("climber", 2, 0)

Each `MechanismLigament2d` object represents a stage of the mechanism. It has a three required parameters, a name, an initial length to draw (relative to the size of the `Mechanism2d` object), and an initial angle to draw the ligament in degrees. Ligament angles are relative to the parent ligament, and follow math notation - the same as Rotation2d (counterclockwise-positive). A ligament based on the root with an angle of zero will point right. Two optional parameters let you change the width (also relative to the size of the Mechanism2d object) and the color. Call `append()`/`Append()` on a root node or ligament node to add another node to the figure. In Java, pass a constructed `MechanismLigament2d` object to add it. In C++, pass the construction parameters in order to construct and add a ligament.

JAVA

    48    // MechanismLigament2d objects represent each "section"/"stage" of the mechanism, and are based
    49    // off the root node or another ligament object
    50    m_elevator = root.append(new MechanismLigament2d("elevator", kElevatorMinimumLength, 90));
    51    m_wrist =
    52        m_elevator.append(
    53            new MechanismLigament2d("wrist", 0.5, 90, 6, new Color8Bit(Color.kPurple)));

C++

    63  // MechanismLigament2d objects represent each "section"/"stage" of the
    64  // mechanism, and are based off the root node or another ligament object
    65  frc::MechanismLigament2d* m_elevator =
    66      m_root->Append<frc::MechanismLigament2d>("elevator", 1, 90_deg);
    67  frc::MechanismLigament2d* m_wrist =
    68      m_elevator->Append<frc::MechanismLigament2d>(
    69          "wrist", 0.5, 90_deg, 6, frc::Color8Bit{frc::Color::kPurple});

PYTHON

    37        # MechanismLigament2d objects represent each "section"/"stage" of the mechanism, and are based
    38        # off the root node or another ligament object
    39        self.elevator = self.root.appendLigament(
    40            "elevator", self.kElevatorMinimumLength, 90
    41        )
    42        self.wrist = self.elevator.appendLigament(
    43            "wrist", 0.5, 90, 6, wpilib.Color8Bit(wpilib.Color.kPurple)
    44        )

Then, publish the `Mechanism2d` object to NetworkTables:

JAVA

    55    // post the mechanism to the dashboard
    56    SmartDashboard.putData("Mech2d", mech);

C++

    36    // publish to dashboard
    37    frc::SmartDashboard::PutData("Mech2d", &m_mech);

PYTHON

    46        # post the mechanism to the dashboard
    47        wpilib.SmartDashboard.putData("Mech2d", self.mech)

Note

The `Mechanism2d` instance can also be sent using a lower-level NetworkTables API or using the Shuffleboard API. In this case, the `SmartDashboard` API was used, meaning that the Mechanism2d widget will appear under the `SmartDashboard` table name.

To manipulate a ligament angle or length, call `setLength()` or `setAngle()` on the `MechanismLigament2d` object. When manipulating ligament length based off of sensor measurements, make sure to add the minimum length to prevent 0-length (and therefore invisible) ligaments.

JAVA

    59  @Override
    60  public void robotPeriodic() {
    61    // update the dashboard mechanism's state
    62    m_elevator.setLength(kElevatorMinimumLength + m_elevatorEncoder.getDistance());
    63    m_wrist.setAngle(m_wristPot.get());
    64  }

C++

    40  void RobotPeriodic() override {
    41    // update the dashboard mechanism's state
    42    m_elevator->SetLength(kElevatorMinimumLength +
    43                          m_elevatorEncoder.GetDistance());
    44    m_wrist->SetAngle(units::degree_t{m_wristPotentiometer.Get()});
    45  }

PYTHON

    49    def robotPeriodic(self):
    50        # update the dashboard mechanism's state
    51        self.elevator.setLength(
    52            self.kElevatorMinimumLength + self.elevatorEncoder.getDistance()
    53        )
    54        self.wrist.setAngle(self.wristPot.get())

## Viewing the Mechanism2d in Glass

After sending the `Mechanism2d` instance over NetworkTables, the Mechanism2d widget can be added to Glass by selecting NetworkTables in the menu bar, choosing the table name that the instance was sent over, and then clicking on the Field button.

Once the widget appears as shown below, you can resize and place it on the Glass workspace as you desire. Right-clicking the top of the widget will allow you to customize the name of the widget. As the wrist potentiometer and elevator encoder changes, the mechanism will update in the widget.

## Viewing the Mechanism2d in AdvantageScope

AdvantageScope is an alternative option for viewing a `Mechanism2d` object, including data recorded to a log file using WPILib data logs. Both 2D and 3D visualizations are supported. See the documentation for the mechanism and 3D field tabs for more details.

## Next Steps

As mentioned above, the Mechanism2d visualization can be combined with Physics Simulation to help you program mechanisms before your robot is built. The ArmSimulation (Java / C++ / Python) and ElevatorSimulation (Java / C++ / Python) examples combine physics simulation and Mechanism2d visualization so that you can practice programming a single jointed arm and elevator without a robot.