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.math.geometry.Rotation2d;
008import edu.wpi.first.networktables.DoubleEntry;
009import edu.wpi.first.networktables.NetworkTable;
010import edu.wpi.first.networktables.StringEntry;
011import edu.wpi.first.networktables.StringPublisher;
012import edu.wpi.first.networktables.StringTopic;
013import edu.wpi.first.wpilibj.util.Color8Bit;
014
015/**
016 * Ligament node on a Mechanism2d. A ligament can have its length changed (like an elevator) or
017 * angle changed, like an arm.
018 *
019 * @see Mechanism2d
020 */
021public class MechanismLigament2d extends MechanismObject2d {
022  private StringPublisher m_typePub;
023  private double m_angle;
024  private DoubleEntry m_angleEntry;
025  private String m_color;
026  private StringEntry m_colorEntry;
027  private double m_length;
028  private DoubleEntry m_lengthEntry;
029  private double m_weight;
030  private DoubleEntry m_weightEntry;
031
032  private static String kSmartDashboardType = "line";
033
034  /**
035   * Create a new ligament.
036   *
037   * @param name The ligament name.
038   * @param length The ligament length.
039   * @param angle The ligament angle in degrees.
040   * @param lineWidth The ligament's line width.
041   * @param color The ligament's color.
042   */
043  public MechanismLigament2d(
044      String name, double length, double angle, double lineWidth, Color8Bit color) {
045    super(name);
046    setColor(color);
047    setLength(length);
048    setAngle(angle);
049    setLineWeight(lineWidth);
050  }
051
052  /**
053   * Create a new ligament with the default color (orange) and thickness (6).
054   *
055   * @param name The ligament's name.
056   * @param length The ligament's length.
057   * @param angle The ligament's angle relative to its parent in degrees.
058   */
059  public MechanismLigament2d(String name, double length, double angle) {
060    this(name, length, angle, 10, new Color8Bit(235, 137, 52));
061  }
062
063  @Override
064  public void close() {
065    super.close();
066    if (m_typePub != null) {
067      m_typePub.close();
068    }
069    if (m_angleEntry != null) {
070      m_angleEntry.close();
071    }
072    if (m_colorEntry != null) {
073      m_colorEntry.close();
074    }
075    if (m_lengthEntry != null) {
076      m_lengthEntry.close();
077    }
078    if (m_weightEntry != null) {
079      m_weightEntry.close();
080    }
081  }
082
083  /**
084   * Set the ligament's angle relative to its parent.
085   *
086   * @param degrees the angle in degrees
087   */
088  public final synchronized void setAngle(double degrees) {
089    m_angle = degrees;
090    if (m_angleEntry != null) {
091      m_angleEntry.set(degrees);
092    }
093  }
094
095  /**
096   * Set the ligament's angle relative to its parent.
097   *
098   * @param angle the angle
099   */
100  public synchronized void setAngle(Rotation2d angle) {
101    setAngle(angle.getDegrees());
102  }
103
104  /**
105   * Get the ligament's angle relative to its parent.
106   *
107   * @return the angle in degrees
108   */
109  public synchronized double getAngle() {
110    if (m_angleEntry != null) {
111      m_angle = m_angleEntry.get();
112    }
113    return m_angle;
114  }
115
116  /**
117   * Set the ligament's length.
118   *
119   * @param length the line length
120   */
121  public final synchronized void setLength(double length) {
122    m_length = length;
123    if (m_lengthEntry != null) {
124      m_lengthEntry.set(length);
125    }
126  }
127
128  /**
129   * Get the ligament length.
130   *
131   * @return the line length
132   */
133  public synchronized double getLength() {
134    if (m_lengthEntry != null) {
135      m_length = m_lengthEntry.get();
136    }
137    return m_length;
138  }
139
140  /**
141   * Set the ligament color.
142   *
143   * @param color the color of the line
144   */
145  public final synchronized void setColor(Color8Bit color) {
146    m_color = String.format("#%02X%02X%02X", color.red, color.green, color.blue);
147    if (m_colorEntry != null) {
148      m_colorEntry.set(m_color);
149    }
150  }
151
152  /**
153   * Get the ligament color.
154   *
155   * @return the color of the line
156   */
157  public synchronized Color8Bit getColor() {
158    if (m_colorEntry != null) {
159      m_color = m_colorEntry.get();
160    }
161    int r = 0;
162    int g = 0;
163    int b = 0;
164    if (m_color.length() == 7 && m_color.charAt(0) == '#') {
165      try {
166        r = Integer.parseInt(m_color.substring(1, 3), 16);
167        g = Integer.parseInt(m_color.substring(3, 5), 16);
168        b = Integer.parseInt(m_color.substring(5, 7), 16);
169      } catch (NumberFormatException e) {
170        r = 0;
171        g = 0;
172        b = 0;
173      }
174    }
175    return new Color8Bit(r, g, b);
176  }
177
178  /**
179   * Set the line thickness.
180   *
181   * @param weight the line thickness
182   */
183  public final synchronized void setLineWeight(double weight) {
184    m_weight = weight;
185    if (m_weightEntry != null) {
186      m_weightEntry.set(weight);
187    }
188  }
189
190  /**
191   * Get the line thickness.
192   *
193   * @return the line thickness
194   */
195  public synchronized double getLineWeight() {
196    if (m_weightEntry != null) {
197      m_weight = m_weightEntry.get();
198    }
199    return m_weight;
200  }
201
202  @Override
203  protected void updateEntries(NetworkTable table) {
204    if (m_typePub != null) {
205      m_typePub.close();
206    }
207    m_typePub =
208        table
209            .getStringTopic(".type")
210            .publishEx(
211                StringTopic.kTypeString, "{\"SmartDashboard\":\"" + kSmartDashboardType + "\"}");
212    m_typePub.set(kSmartDashboardType);
213
214    if (m_angleEntry != null) {
215      m_angleEntry.close();
216    }
217    m_angleEntry = table.getDoubleTopic("angle").getEntry(0.0);
218    m_angleEntry.set(m_angle);
219
220    if (m_lengthEntry != null) {
221      m_lengthEntry.close();
222    }
223    m_lengthEntry = table.getDoubleTopic("length").getEntry(0.0);
224    m_lengthEntry.set(m_length);
225
226    if (m_colorEntry != null) {
227      m_colorEntry.close();
228    }
229    m_colorEntry = table.getStringTopic("color").getEntry("");
230    m_colorEntry.set(m_color);
231
232    if (m_weightEntry != null) {
233      m_weightEntry.close();
234    }
235    m_weightEntry = table.getDoubleTopic("weight").getEntry(0.0);
236    m_weightEntry.set(m_weight);
237  }
238}