hypergraph_physics

Hypergraph → pymunk body construction; merges Fixed-triangle edges into rigid bodies.

Hypergraph-based physics body generation.

This module provides functions to convert a pylinkage hypergraph representation into pymunk physics bodies and constraints. Each edge in the hypergraph becomes a rigid body (bar), and nodes where multiple bodies meet get PivotJoint constraints.

Hyperedges define rigid body groups: all nodes in a hyperedge share one pymunk body.

class leggedsnake.hypergraph_physics.PhysicsMapping(edge_to_body: dict[str, ~pymunk.body.Body] = <factory>, node_to_bodies: dict[str, set[~pymunk.body.Body]] = <factory>, node_to_anchors: dict[str, dict[~pymunk.body.Body, ~pymunk.vec2d.Vec2d]] = <factory>, constraints: list[~pymunk.constraints.PivotJoint] = <factory>, motors: list[~pymunk.constraints.SimpleMotor] = <factory>, motor_node_ids: list[str] = <factory>, motor_pivots: list[~pymunk.constraints.PivotJoint] = <factory>, gear_joints: list[~pymunk.constraints.GearJoint] = <factory>)

Bases: object

Maps hypergraph elements to pymunk physics objects.

Variables:
  • edge_to_body (dict[str, pm.Body]) – Maps edge IDs to their corresponding pymunk bodies.

  • node_to_bodies (dict[str, set[pm.Body]]) – Maps node IDs to all bodies that share that joint position.

  • node_to_anchors (dict[str, dict[pm.Body, pm.Vec2d]]) – Maps node IDs to local anchor positions on each body.

  • constraints (list[pm.PivotJoint]) – All pivot joint constraints created.

  • motors (list[pm.SimpleMotor]) – All motor constraints for driver nodes.

  • motor_node_ids (list[str]) – Driver node ID for each motor (parallel to motors list).

  • motor_pivots (list[pm.PivotJoint]) – Pivot joints associated with motors (currently unused, kept for compatibility).

  • gear_joints (list[pm.GearJoint]) – Gear constraints that lock cranks sharing the same motor rate to a common shaft, preventing torque-limited motors from drifting out of phase under asymmetric ground load.

__init__(edge_to_body: dict[str, ~pymunk.body.Body] = <factory>, node_to_bodies: dict[str, set[~pymunk.body.Body]] = <factory>, node_to_anchors: dict[str, dict[~pymunk.body.Body, ~pymunk.vec2d.Vec2d]] = <factory>, constraints: list[~pymunk.constraints.PivotJoint] = <factory>, motors: list[~pymunk.constraints.SimpleMotor] = <factory>, motor_node_ids: list[str] = <factory>, motor_pivots: list[~pymunk.constraints.PivotJoint] = <factory>, gear_joints: list[~pymunk.constraints.GearJoint] = <factory>) None
constraints: list[PivotJoint]
edge_to_body: dict[str, Body]
gear_joints: list[GearJoint]
motor_node_ids: list[str]
motor_pivots: list[PivotJoint]
motors: list[SimpleMotor]
node_to_anchors: dict[str, dict[Body, Vec2d]]
node_to_bodies: dict[str, set[Body]]
leggedsnake.hypergraph_physics.create_bodies_from_hypergraph(hg: HypergraphLinkage, dimensions: Dimensions, space: Space, load_body: Body, density: float, thickness: float, shape_filter: ShapeFilter | None, motor_rates: float | dict[str, float] | None = None, foot_edge_ids: set[str] | None = None, non_foot_filter: ShapeFilter | None = None) PhysicsMapping

Create pymunk bodies from a hypergraph representation.

Each edge in the hypergraph becomes a rigid body with a segment shape, except for edges in hyperedges (rigid groups) which are merged into single bodies.

Parameters:
  • hg (HypergraphLinkage) – The hypergraph representation of the linkage.

  • dimensions (Dimensions) – Geometric data (positions, distances, angles) for the hypergraph.

  • space (pm.Space) – The pymunk space to add bodies to.

  • load_body (pm.Body) – The frame/chassis body that ground nodes attach to.

  • density (float) – Density for body mass calculation.

  • thickness (float) – Radius of segment shapes.

  • shape_filter (pm.ShapeFilter | None) – Collision filter for foot segments (collide with ground).

  • motor_rates (MotorRates | None) – Motor angular velocities. Single float applies to all drivers. Dict maps driver node IDs to individual rates (multi-DOF). If None, falls back to driver angular velocity from dimensions.

  • foot_edge_ids (set[str] | None) – Edge IDs that should collide with the ground. When set, only these edges use shape_filter; all other edges use non_foot_filter instead (which should mask out ground collisions). None disables selective collision — every edge uses shape_filter.

  • non_foot_filter (pm.ShapeFilter | None) – Collision filter for edges that are not in foot_edge_ids. Typically configured to ignore ground collisions.

Returns:

Mapping of hypergraph elements to physics objects.

Return type:

PhysicsMapping

leggedsnake.hypergraph_physics.get_node_world_position(node_id: str, mapping: PhysicsMapping) Vec2d

Get the current world position of a node from physics bodies.

Parameters:
  • node_id (str) – The node ID to query.

  • mapping (PhysicsMapping) – The physics mapping containing body references.

Returns:

The world position of the node.

Return type:

pm.Vec2d