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++

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);
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);
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.

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)));
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});
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:

55    // post the mechanism to the dashboard
56    SmartDashboard.putData("Mech2d", mech);
36    // publish to dashboard
37    frc::SmartDashboard::PutData("Mech2d", &m_mech);
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.

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  }
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  }
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.

../../../../_images/select-mechanism2d.png

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.

../../../../_images/mechanism2d-widget.png

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.

Screenshot of an AdvantageScope window displaying a robot and mechanism in 3D.

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.