newton.sensors.SensorContact#
- class newton.sensors.SensorContact(model, *, sensing_obj_bodies=None, sensing_obj_shapes=None, counterpart_bodies=None, counterpart_shapes=None, measure_total=True, verbose=None, request_contact_attributes=True, include_total=None)[source]#
Bases:
objectMeasures contact forces on a set of sensing objects (bodies or shapes).
In its simplest form the sensor reports
total_force— the total contact force on each sensing object. Optionally, specify counterparts to get a per-counterpart breakdown inforce_matrix.total_forceandforce_matrixare each nullable:total_forceisNonewhenmeasure_total=False;force_matrixisNonewhen no counterparts are specified.Multi-world behavior
When the model contains multiple worlds, counterpart mappings are resolved per-world. The collision pipeline and solver are expected to produce only within-world contacts, so cross-world force accumulation does not arise in practice. Global counterparts (e.g. ground plane) contribute to every world they contact.
In single-world models where no
add_world()call was made (all entities are global /world=-1), the sensor treats the entire model as one implicit world and all entities are valid sensing objects.When counterparts are specified, the force matrix has shape
(sum_of_sensors_across_worlds, max_counterparts)wheremax_counterpartsis the maximum counterpart count of any single world. Row order matchessensing_obj_idx. Columns beyond a world’s own counterpart count are zero-padded.sensing_obj_idxandcounterpart_indicesare flat lists that describe the structure of the output arrays.Terms
Sensing object – body or shape carrying a contact sensor.
Counterpart – the other body or shape in a contact interaction.
Construction and update order
SensorContactrequests theforceextended attribute from the model at init, so aContactsobject created afterwards (viaModel.contacts()or directly) will include it automatically.update()reads fromcontacts.force. Callsolver.update_contacts(contacts)beforesensor.update()so that contact forces are current.Parameters that select bodies or shapes accept label patterns – see Label Matching.
Example
Measure total contact force on a sphere resting on the ground:
import warp as wp import newton from newton.sensors import SensorContact builder = newton.ModelBuilder() builder.add_ground_plane() body = builder.add_body(xform=wp.transform((0, 0, 0.1), wp.quat_identity())) builder.add_shape_sphere(body, radius=0.1, label="ball") model = builder.finalize() sensor = SensorContact(model, sensing_obj_shapes="ball") solver = newton.solvers.SolverMuJoCo(model) state = model.state() contacts = model.contacts() solver.step(state, state, None, None, dt=1.0 / 60.0) solver.update_contacts(contacts) sensor.update(state, contacts) force = sensor.total_force.numpy() # (n_sensing_objs, 3)
- Raises:
ValueError – If the configuration of sensing/counterpart objects is invalid.
- class ObjectType(*values)#
Bases:
EnumDeprecated. Type tag for entries in legacy
sensing_objsandcounterpartsproperties.- BODY = 2#
Individual body.
- SHAPE = 1#
Individual shape.
- TOTAL = 0#
Total force entry.
- __init__(model, *, sensing_obj_bodies=None, sensing_obj_shapes=None, counterpart_bodies=None, counterpart_shapes=None, measure_total=True, verbose=None, request_contact_attributes=True, include_total=None)#
Initialize the SensorContact.
Exactly one of
sensing_obj_bodiesorsensing_obj_shapesmust be specified to define the sensing objects. At most one ofcounterpart_bodiesorcounterpart_shapesmay be specified. If neither is specified, onlytotal_forceis available (no per-counterpart breakdown).- Parameters:
model (Model) – The simulation model providing shape/body definitions and world layout.
sensing_obj_bodies (str | list[str] | list[int] | None) – List of body indices, single pattern to match against body labels, or list of patterns where any one matches.
sensing_obj_shapes (str | list[str] | list[int] | None) – List of shape indices, single pattern to match against shape labels, or list of patterns where any one matches.
counterpart_bodies (str | list[str] | list[int] | None) – List of body indices, single pattern to match against body labels, or list of patterns where any one matches.
counterpart_shapes (str | list[str] | list[int] | None) – List of shape indices, single pattern to match against shape labels, or list of patterns where any one matches.
measure_total (bool) – If True (default),
total_forceis allocated. If False,total_forceis None.verbose (bool | None) – If True, print details. If None, uses
wp.config.verbose.request_contact_attributes (bool) – If True (default), transparently request the extended contact attribute
forcefrom the model.include_total (bool | None) – Deprecated. Use
measure_totalinstead.
- update(state, contacts)#
Update the contact sensor readings based on the provided state and contacts.
Computes world-frame transforms for all sensing objects and evaluates contact forces (total and/or per-counterpart, depending on sensor configuration).
- Parameters:
- Raises:
ValueError – If
contacts.forceis None.ValueError – If
contacts.devicedoes not match the sensor’s device.
- counterpart_indices: list[list[int]]#
Counterpart body or shape indices per sensing object.
counterpart_indices[i]lists the counterparts for rowi. Global counterparts appear first, followed by per-world locals in ascending index order.
- counterpart_type: Literal['body', 'shape'] | None#
Whether
counterpart_indicescontains body indices ("body") or shape indices ("shape").Nonewhen no counterparts are specified.
- property counterparts: list[list[tuple[int, ObjectType]]]#
Deprecated. Use
counterpart_indicesandcounterpart_typeinstead.
- force_matrix: wp.array2d(dtype=wp.vec3) | None#
Per-counterpart contact forces [N], shape
(n_sensing_objs, max_counterparts), dtypevec3. Entry[i, j]is the force on sensing objectifrom counterpartcounterpart_indices[i][j], in world frame.Nonewhen no counterparts are specified.
- property net_force: array2d#
Deprecated. Use
total_forceandforce_matrixinstead.
- property reading_indices: list[list[list[int]]]#
Deprecated. Active counterpart indices per sensing object, per world.
- sensing_obj_idx: list[int]#
Body or shape index per sensing object, matching the row of output arrays. For
list[int]inputs the caller’s order is preserved; for string patterns the order follows ascending body/shape index.
- sensing_obj_transforms: wp.array(dtype=wp.transform)#
World-frame transforms of sensing objects [m, unitless quaternion], shape
(n_sensing_objs,), dtypetransform.
- sensing_obj_type: Literal['body', 'shape']#
Whether
sensing_obj_idxcontains body indices ("body") or shape indices ("shape").
- property sensing_objs: list[list[tuple[int, ObjectType]]]#
Deprecated. Use
sensing_obj_idxandsensing_obj_typeinstead.