allwpilib icon indicating copy to clipboard operation
allwpilib copied to clipboard

Mechanism2dRoot enhancements

Open virtuald opened this issue 3 years ago • 4 comments
trafficstars

Drawing:

  • Helpers for creating shapes
  • Add ligaments that aren't directly connected to the root
    • The root is convenient because you can shift the position of a bunch of objects, so it feels really more like a group of items.
    • In particular, I'd like to move the object around by moving its 'center'... but currently I'd have to compute that, or draw it carefully.

API goodness:

  • Mechanism to iterate children
  • auto-create names for ligaments
  • Set defaults for created children when not specified (color, lineweight)
  • If one creates a large number of ligaments that aren't really doing anything, it would be convenient if I only had to keep the root around instead of creating a list of children. In particular, SetColor/SetLineWeight would be nice.

Interaction:

  • It would be convenient if I could click on something and register that somehow. (Eg, I click a button and the sim responds by making a ball appear)

... basically reinvent tkinter's canvas API :shipit:

virtuald avatar Mar 15 '22 03:03 virtuald

Mechanism2d is designed for visualization of robot mechanisms: eg single/2-jointed arms, elevators, etc. It’s not designed to be a generic drawing canvas (although clearly it can be abused to do that). Also, its NT representation has several keys per element, so trying to do large numbers of elements is inefficient on the NT side.

Instead of trying to turn Mechanism2d into a generic canvas, maybe propose a new Canvas Sendable element with an appropriate API and NT representation for that use case?

PeterJohnson avatar Mar 16 '22 13:03 PeterJohnson

I think it would be better (but similar) to define a Canvas sendable, and build the mechanism2d on top of it. The key is it would be good to be able to draw what you're simulating.

... I was going to post a gif of something I'm working on to illustrate what I'm trying to accomplish, but apparently recording OpenGL on Linux is annoying and doesn't seem to work.

FWIW, these are the helpers I'm using at the moment:

@dataclasses.dataclass
class Shape:
    root: wpilib.MechanismRoot2d
    items: typing.List[wpilib.MechanismLigament2d]

    def setPosition(self, x: float, y: float):
        self.root.setPosition(x, y)

    def setColor(self, c: wpilib.Color8Bit):
        for item in self.items:
            item.setColor(c)


class Mechanism(wpilib.Mechanism2d):
    def __init__(self, width: float, height: float) -> None:
        super().__init__(width, height)

    def make_point(self, name: str, cx: float, cy: float, sz: int = 10) -> Shape:
        root = self.getRoot(name, cx, cy)
        return self._make(root, 0.50, 0, 1, sz)

    def make_triangle(
        self, name: str, cx: float, cy: float, side: float, line_width=6
    ) -> Shape:
        x = cx + side / 2
        y = cy - side / 2
        root = self.getRoot(name, x, y)
        return self._make(root, side, 120, 3, line_width)

    def make_hex(
        self, name: str, x: float, y: float, side: float, line_width=6
    ) -> Shape:
        # x, y are near bottom right corner
        root = self.getRoot(name, x, y)
        return self._make(root, side, 60, 6, line_width)

    def _make(
        self,
        root: wpilib.MechanismRoot2d,
        side: float,
        angle: float,
        n: int,
        line_width,
    ) -> Shape:
        item = root
        items = []
        for i in range(n):
            item = item.appendLigament(f"{i}", side, angle, line_width)
            items.append(item)

        return Shape(root, items)

virtuald avatar Mar 20 '22 06:03 virtuald

image

virtuald avatar Mar 20 '22 06:03 virtuald

Finally got around to making a video of it: https://youtu.be/MHMJc4h1hnw

virtuald avatar Apr 11 '22 17:04 virtuald