001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj.smartdashboard; 006 007import edu.wpi.first.networktables.NetworkTable; 008import edu.wpi.first.networktables.NetworkTableEntry; 009import java.util.HashMap; 010import java.util.Map; 011 012/** 013 * Root Mechanism2d node. 014 * 015 * <p>A root is the anchor point of other nodes (such as ligaments). 016 * 017 * <p>Do not create objects of this class directly! Obtain instances from the {@link 018 * Mechanism2d#getRoot(String, double, double)} factory method. 019 * 020 * <p>Append other nodes by using {@link #append(MechanismObject2d)}. 021 */ 022public final class MechanismRoot2d { 023 private final String m_name; 024 private NetworkTable m_table; 025 private final Map<String, MechanismObject2d> m_objects = new HashMap<>(1); 026 private double m_x; 027 private NetworkTableEntry m_xEntry; 028 private double m_y; 029 private NetworkTableEntry m_yEntry; 030 031 /** 032 * Package-private constructor for roots. 033 * 034 * @param name name 035 * @param x x coordinate of root (provide only when constructing a root node) 036 * @param y y coordinate of root (provide only when constructing a root node) 037 */ 038 MechanismRoot2d(String name, double x, double y) { 039 m_name = name; 040 m_x = x; 041 m_y = y; 042 } 043 044 /** 045 * Append a Mechanism object that is based on this one. 046 * 047 * @param <T> The object type. 048 * @param object the object to add. 049 * @return the object given as a parameter, useful for variable assignments and call chaining. 050 * @throws UnsupportedOperationException if the object's name is already used - object names must 051 * be unique. 052 */ 053 public synchronized <T extends MechanismObject2d> T append(T object) { 054 if (m_objects.containsKey(object.getName())) { 055 throw new UnsupportedOperationException("Mechanism object names must be unique!"); 056 } 057 m_objects.put(object.getName(), object); 058 if (m_table != null) { 059 object.update(m_table.getSubTable(object.getName())); 060 } 061 return object; 062 } 063 064 /** 065 * Set the root's position. 066 * 067 * @param x new x coordinate 068 * @param y new y coordinate 069 */ 070 public synchronized void setPosition(double x, double y) { 071 m_x = x; 072 m_y = y; 073 } 074 075 synchronized void update(NetworkTable table) { 076 m_table = table; 077 m_xEntry = m_table.getEntry("x"); 078 m_yEntry = m_table.getEntry("y"); 079 flush(); 080 for (MechanismObject2d obj : m_objects.values()) { 081 obj.update(m_table.getSubTable(obj.getName())); 082 } 083 } 084 085 public String getName() { 086 return m_name; 087 } 088 089 private void flush() { 090 if (m_xEntry != null) { 091 m_xEntry.setDouble(m_x); 092 } 093 if (m_yEntry != null) { 094 m_yEntry.setDouble(m_y); 095 } 096 } 097}