newton.sensors.SensorContact#
- class newton.sensors.SensorContact(model, *, sensing_obj_bodies=None, sensing_obj_shapes=None, counterpart_bodies=None, counterpart_shapes=None, include_total=True, verbose=None, request_contact_attributes=True)[source]#
Bases:
objectMeasures net contact forces on a set of sensing objects (bodies or shapes).
In its simplest form the sensor reports the total contact force acting on each sensing object. Optionally, specify counterparts to break the force down per contacting body or shape. With
include_total=True(default) a total-force column is prepended.The result is a force matrix: one row per sensing object, one column per counterpart reading.
Multi-world behaviour
When the model contains multiple worlds, pair tables are built per-world. Cross-world shape pairs are excluded – only within-world and global counterparts (e.g. ground plane) contribute. Global bodies and shapes cannot be sensing objects.
The force matrix has shape
(sum_of_sensors_across_worlds, max_readings)wheremax_readingsis the maximum counterpart count of any single world. Rows are world-contiguous (world 0 first, then world 1, …). Columns beyond a world’s own reading count are zero-padded.sensing_objs,counterparts, andreading_indicesare per-world nested lists indexed asattr[world][i].Terms
Sensing object – body or shape carrying a contact sensor.
Counterpart – the other body or shape in a contact interaction.
Force reading – one entry of the force matrix (
vec3).
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 net 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.net_force.numpy() # (n_sensing_objs, max_readings, 3)
- Raises:
ValueError – If the configuration of sensing/counterpart objects is invalid.
- class ObjectType(*values)#
Bases:
EnumType tag for entries in
sensing_objsandcounterparts.- BODY = 2#
Individual body.
- SHAPE = 1#
Individual shape.
- TOTAL = 0#
Total force entry. Only applies to counterparts.
- __init__(model, *, sensing_obj_bodies=None, sensing_obj_shapes=None, counterpart_bodies=None, counterpart_shapes=None, include_total=True, verbose=None, request_contact_attributes=True)#
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, the sensor will read the net contact force for each sensing object.- Parameters:
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.
include_total (bool) – If True and counterparts are specified, add a reading for the total contact force for each sensing object. Does nothing when no counterparts are specified.
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.
- 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 net contact forces for each sensing-object/counterpart pair.
- counterparts: list[list[tuple[int, ObjectType]]]#
Index and type of each counterpart, per world. Columns of the force matrix.
- net_force: array(ndim=2, dtype=vec3f)#
Net contact forces [N], shape
(n_sensing_objs, max_readings), dtypevec3. Entry[i, j]is the force on sensing objectifrom counterpartj, in world frame.
- sensing_obj_transforms: array(ndim=1, dtype=transformf)#
World-frame transforms of sensing objects [m, unitless quaternion], shape
(n_sensing_objs,), dtypetransform.