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:
objectMaps 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:
- 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