Skip to content

fix(hypergraph): build a slider from a prismatic node in to_mechanism - #60

Merged
HugoFara merged 1 commit into
mainfrom
fix/hypergraph-slider-crank
Sep 18, 2026
Merged

HugoFara merged 1 commit into
mainfrom
fix/hypergraph-slider-crank

Conversation

@HugoFara

Copy link
Copy Markdown
Owner

Closes #56.

A slider-crank did not survive Linkage.to_hypergraph() → to_mechanism(): it assembled, then jammed as soon as the crank turned.

from_sim_linkage tagged only LinearActuator nodes PRISMATIC; an RRPDyad (or PPDyad) output stayed REVOLUTE. Its guide is a hyperedge over the two line anchors and the slider, which the clique expansion from #55 turns into two extra neighbours. The dyad's output is now tagged PRISMATIC — it is the slider block — and compute_mobility reports 1 DOF for the slider-crank instead of 0.

to_mechanism built every driven node from its first two solved neighbours as two Links regardless of joint_type, so the slider became an RRR dyad pinned to a ground node at its initial distance. A PRISMATIC node is now read the way from_sim_linkage writes it: one edge to its revolute anchor, one 3-node hyperedge for the line. It becomes a PrismaticJoint with axis / line_point taken from the two line nodes and a single link to the anchor, scheduled once that anchor is solved.

The round trip reproduces Linkage.step() to ~1e-15 over a full cycle (the issue's reproducer is now a test).

Mechanism only holds a slide line fixed to the frame, so the cases it cannot represent raise NotImplementedError with a reason instead of mis-solving: a guide on a moving link, a PPDyad-style double slider, a prismatic node with no guide hyperedge.

Not in scope, noted for later:

  • from_mechanism still drops the slide line of a PrismaticJoint (it has no joints on the line to hang a hyperedge on), so slider_crank() → from_mechanism → to_mechanism fails as before.
  • A LinearActuator driver node is still built as a revolute crank by to_mechanism.
  • The mechanism's indeterminacy() counts a ground joint that only sits on the ground link as a revolute pair, so it reports −1 for the round-tripped slider-crank; compute_mobility on the hypergraph is right.

A slider-crank did not survive Linkage.to_hypergraph() → to_mechanism()
(#56), for two reasons.

from_sim_linkage tagged only LinearActuator nodes as PRISMATIC and left
the output of an RRPDyad (and PPDyad) REVOLUTE. Its guide is a hyperedge
over the two line anchors and the slider, which the clique expansion
from #55 turns into two more neighbours. Tag those nodes PRISMATIC: the
dyad's output is the slider block. compute_mobility then counts it as
such and a slider-crank reports 1 DOF instead of 0.

to_mechanism built every driven node from its first two solved
neighbours as two Links, whatever its joint_type, so the slider became
an RRR dyad pinned to a ground node at its initial distance and jammed
as soon as the crank turned. A PRISMATIC node is now read the way
from_sim_linkage writes it — one edge to its revolute anchor, one
hyperedge of three nodes for the line — and becomes a PrismaticJoint
with axis and line_point taken from the two line nodes, linked to the
anchor alone. It is scheduled once that anchor is solved. The round
trip reproduces Linkage.step() to machine precision.

Mechanism only holds a slide line fixed to the frame, so a guide on a
moving link, a PPDyad-style double slider and a prismatic node without
a guide raise NotImplementedError instead of being mis-solved.

Closes #56
@HugoFara
HugoFara merged commit 0564937 into main Sep 18, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Slider-crank does not survive Linkage.to_hypergraph() → to_mechanism()

1 participant