mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-23 01:21:42 +00:00
[glass, wpilib] Rewrite Mechanism2d (#3281)
Substantially improves Mechanism2d by moving it to NetworkTables and adding a robot API to create the mechanism elements, instead of requiring a JSON file. Co-authored-by: Peter Johnson <johnson.peter@gmail.com>
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <hal/SimDevice.h>
|
||||
#include <wpi/StringMap.h>
|
||||
|
||||
#include "frc/geometry/Pose2d.h"
|
||||
#include "frc/geometry/Rotation2d.h"
|
||||
|
||||
namespace frc {
|
||||
class Mechanism2D {
|
||||
public:
|
||||
Mechanism2D();
|
||||
|
||||
/**
|
||||
* Set/Create the angle of a ligament
|
||||
*
|
||||
* @param ligamentPath json path to the ligament
|
||||
* @param angle to set the ligament
|
||||
*/
|
||||
void SetLigamentAngle(const wpi::Twine& ligamentPath, float angle);
|
||||
|
||||
/**
|
||||
* Set/Create the length of a ligament
|
||||
*
|
||||
* @param ligamentPath json path to the ligament
|
||||
* @param length to set the ligament
|
||||
*/
|
||||
void SetLigamentLength(const wpi::Twine& ligamentPath, float length);
|
||||
|
||||
private:
|
||||
wpi::StringMap<hal::SimDouble> createdItems;
|
||||
hal::SimDevice m_device;
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <networktables/NetworkTableEntry.h>
|
||||
#include <wpi/StringMap.h>
|
||||
#include <wpi/mutex.h>
|
||||
|
||||
#include "frc/smartdashboard/MechanismRoot2d.h"
|
||||
#include "frc/smartdashboard/Sendable.h"
|
||||
#include "frc/smartdashboard/SendableHelper.h"
|
||||
#include "frc/util/Color8Bit.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* Visual 2D representation of arms, elevators, and general mechanisms; through
|
||||
* a node-based API.
|
||||
*
|
||||
* A Mechanism2d object is published and contains at least one root node. Other
|
||||
* nodes (such as ligaments) are recursively based on other nodes.
|
||||
*
|
||||
* Except for the Mechanism2d container object, none of the objects should be
|
||||
* passed or interacted with by value! Obtain pointers from factory methods such
|
||||
* as Mechanism2d.GetRoot() and MechanismObject2d.Append<>(). The Mechanism2d
|
||||
* container object owns the root nodes, and each node internally owns the nodes
|
||||
* based on it. Beware not to let the Mechanism2d object out of scope - all
|
||||
* nodes will be recursively destructed!
|
||||
*
|
||||
* @see MechanismObject2d
|
||||
* @see MechanismLigament2d
|
||||
* @see MechanismRoot2d
|
||||
*/
|
||||
class Mechanism2d : public Sendable, public SendableHelper<Mechanism2d> {
|
||||
public:
|
||||
/**
|
||||
* Create a new Mechanism2d with the given dimensions and background color.
|
||||
*
|
||||
* @param width the width
|
||||
* @param height the height
|
||||
*/
|
||||
Mechanism2d(double width, double height,
|
||||
const Color8Bit& backgroundColor = {0, 0, 32});
|
||||
|
||||
/**
|
||||
* Get or create a root in this Mechanism2d with the given name and
|
||||
* position.
|
||||
*
|
||||
* <p>If a root with the given name already exists, the given x and y
|
||||
* coordinates are not used.
|
||||
*
|
||||
* @param name the root name
|
||||
* @param x the root x coordinate
|
||||
* @param y the root y coordinate
|
||||
* @return a new root object, or the existing one with the given name.
|
||||
*/
|
||||
MechanismRoot2d* GetRoot(wpi::StringRef name, double x, double y);
|
||||
|
||||
/**
|
||||
* Set the Mechanism2d background color.
|
||||
*
|
||||
* @param color the new background color
|
||||
*/
|
||||
void SetBackgroundColor(const Color8Bit& color);
|
||||
|
||||
void InitSendable(SendableBuilder& builder) override;
|
||||
|
||||
private:
|
||||
double m_width;
|
||||
double m_height;
|
||||
char m_color[10];
|
||||
mutable wpi::mutex m_mutex;
|
||||
std::shared_ptr<nt::NetworkTable> m_table;
|
||||
wpi::StringMap<std::unique_ptr<MechanismRoot2d>> m_roots;
|
||||
};
|
||||
} // namespace frc
|
||||
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <networktables/NetworkTableEntry.h>
|
||||
#include <units/angle.h>
|
||||
|
||||
#include "frc/smartdashboard/MechanismObject2d.h"
|
||||
#include "frc/util/Color8Bit.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* Ligament node on a Mechanism2d.
|
||||
*
|
||||
* @see Mechanism2d
|
||||
*/
|
||||
class MechanismLigament2d : public MechanismObject2d {
|
||||
public:
|
||||
MechanismLigament2d(const wpi::Twine& name, double length,
|
||||
units::degree_t angle, double lineWidth = 6,
|
||||
const frc::Color8Bit& color = {235, 137, 52});
|
||||
|
||||
/**
|
||||
* Set the ligament color.
|
||||
*
|
||||
* @param color the color of the line
|
||||
*/
|
||||
void SetColor(const frc::Color8Bit& color);
|
||||
|
||||
/**
|
||||
* Set the ligament's length.
|
||||
*
|
||||
* @param length the line length
|
||||
*/
|
||||
void SetLength(double length);
|
||||
|
||||
/**
|
||||
* Get the ligament length.
|
||||
*
|
||||
* @return the line length
|
||||
*/
|
||||
double GetLength();
|
||||
|
||||
/**
|
||||
* Set the ligament's angle relative to its parent.
|
||||
*
|
||||
* @param degrees the angle
|
||||
*/
|
||||
void SetAngle(units::degree_t angle);
|
||||
|
||||
/**
|
||||
* Get the ligament's angle relative to its parent.
|
||||
*
|
||||
* @return the angle
|
||||
*/
|
||||
double GetAngle();
|
||||
|
||||
/**
|
||||
* Set the line thickness.
|
||||
*
|
||||
* @param weight the line thickness
|
||||
*/
|
||||
void SetLineWeight(double lineWidth);
|
||||
|
||||
protected:
|
||||
void UpdateEntries(std::shared_ptr<NetworkTable> table) override;
|
||||
|
||||
private:
|
||||
void Flush();
|
||||
double m_length;
|
||||
nt::NetworkTableEntry m_lengthEntry;
|
||||
double m_angle;
|
||||
nt::NetworkTableEntry m_angleEntry;
|
||||
double m_weight;
|
||||
nt::NetworkTableEntry m_weightEntry;
|
||||
char m_color[10];
|
||||
nt::NetworkTableEntry m_colorEntry;
|
||||
};
|
||||
} // namespace frc
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <networktables/NetworkTable.h>
|
||||
#include <wpi/StringMap.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* Common base class for all Mechanism2d node types.
|
||||
*
|
||||
* To append another node, call Append with the type of node and its
|
||||
* construction parameters. None of the node types are designed to be
|
||||
* constructed directly, and are owned by their parent node/container - obtain
|
||||
* pointers from the Append function or similar factory methods.
|
||||
*
|
||||
* @see Mechanism2d.
|
||||
*/
|
||||
class MechanismObject2d {
|
||||
friend class Mechanism2d;
|
||||
|
||||
protected:
|
||||
explicit MechanismObject2d(const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Update all entries with new ones from a new table.
|
||||
*
|
||||
* @param table the new table.
|
||||
*/
|
||||
virtual void UpdateEntries(std::shared_ptr<NetworkTable> table) = 0;
|
||||
|
||||
mutable wpi::mutex m_mutex;
|
||||
|
||||
public:
|
||||
virtual ~MechanismObject2d() = default;
|
||||
|
||||
/**
|
||||
* Retrieve the object's name.
|
||||
*
|
||||
* @return the object's name relative to its parent.
|
||||
*/
|
||||
const std::string& GetName() const;
|
||||
|
||||
/**
|
||||
* Append a Mechanism object that is based on this one.
|
||||
*
|
||||
* @param name the name of the new object.
|
||||
* @param args constructor arguments of the object type.
|
||||
* @return the constructed and appended object, useful for variable
|
||||
* assignments and call chaining.
|
||||
* @throw if an object with the given name already exists.
|
||||
*/
|
||||
template <typename T, typename... Args,
|
||||
typename =
|
||||
std::enable_if_t<std::is_convertible_v<T*, MechanismObject2d*>>>
|
||||
T* Append(wpi::StringRef name, Args&&... args) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto& obj = m_objects[name];
|
||||
if (obj) {
|
||||
throw std::runtime_error(("MechanismObject names must be unique! `" +
|
||||
name + "` was inserted twice!")
|
||||
.str());
|
||||
}
|
||||
obj = std::make_unique<T>(name, std::forward<Args>(args)...);
|
||||
T* ex = static_cast<T*>(obj.get());
|
||||
if (m_table) {
|
||||
ex->Update(m_table->GetSubTable(name));
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
wpi::StringMap<std::unique_ptr<MechanismObject2d>> m_objects;
|
||||
std::shared_ptr<NetworkTable> m_table;
|
||||
void Update(std::shared_ptr<NetworkTable> table);
|
||||
};
|
||||
} // namespace frc
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <networktables/NetworkTableEntry.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "MechanismObject2d.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* Root Mechanism2d node.
|
||||
*
|
||||
* Do not create objects of this class directly! Obtain pointers from the
|
||||
* Mechanism2d.GetRoot() factory method.
|
||||
*/
|
||||
class MechanismRoot2d : private MechanismObject2d {
|
||||
friend class Mechanism2d;
|
||||
struct private_init {};
|
||||
|
||||
public:
|
||||
MechanismRoot2d(const wpi::Twine& name, double x, double y,
|
||||
const private_init&);
|
||||
|
||||
/**
|
||||
* Set the root's position.
|
||||
*
|
||||
* @param x new x coordinate
|
||||
* @param y new y coordinate
|
||||
*/
|
||||
void SetPosition(double x, double y);
|
||||
|
||||
using MechanismObject2d::GetName;
|
||||
|
||||
using MechanismObject2d::Append;
|
||||
|
||||
private:
|
||||
void UpdateEntries(std::shared_ptr<NetworkTable> table) override;
|
||||
inline void Flush();
|
||||
double m_x;
|
||||
double m_y;
|
||||
nt::NetworkTableEntry m_posEntry;
|
||||
};
|
||||
} // namespace frc
|
||||
Reference in New Issue
Block a user