The ContactSurface characterizes the intersection of two geometries M and N as a contact surface with a scalar field and a vector field, whose purpose is to support the hydroelastic pressure field contact model as described in:
R. Elandt, E. Drumwright, M. Sherman, and Andy Ruina. A pressure field model for fast, robust approximation of net contact force and moment between nominally rigid objects. IROS 2019: 82388245.
In this section, we give motivation for the concept of contact surface from the hydroelastic pressure field contact model. Here the mathematical discussion is coordinatefree (treatment of the topic without reference to any particular coordinate system); however, our implementation heavily relies on coordinate frames. We borrow terminology from differential geometry.
In this section, the mathematical term compact set (a subset of Euclidean space that is closed and bounded) corresponds to the term geometry (or the space occupied by the geometry) in SceneGraph.
We describe the contact surface πββ between two intersecting compact subsets π and β of βΒ³ with the scalar fields eβ and eβ defined on π β βΒ³ and β β βΒ³ respectively:
eβ : π β β, eβ : β β β.
The contact surface πββ is the surface of equilibrium eβ = eβ. It is the locus of points Q where eβ(Q) equals eβ(Q):
πββ = { Q β π β© β : eβ(Q) = eβ(Q) }.
We can define the scalar field eββ on the surface πββ as a scalar function that assigns Q β πββ the value of eβ(Q), which is the same as eβ(Q):
eββ : πββ β β, eββ(Q) = eβ(Q) = eβ(Q).
We can also define the scalar field hββ on π β© β as the difference between eβ and eβ:
hββ : π β© β β β, hββ(Q) = eβ(Q)  eβ(Q).
It follows that the gradient vector field βhββ on π β© β equals the difference between the gradient vector fields βeβ and βeβ:
βhββ : π β© β β βΒ³, βhββ(Q) = βeβ(Q)  βeβ(Q).
By construction, Q β πββ if and only if hββ(Q) = 0. In other words, πββ is the zero level set of hββ. It follows that, for Q β πββ, βhββ(Q) is orthogonal to the surface πββ at Q in the direction of increasing eβ  eβ.
Notice that the domain of eββ is the twodimensional surface πββ, while the domain of βhββ is the threedimensional compact set π β© β. Even though eββ and βhββ are defined on different domains (πββ and π β© β), our implementation only represents them on their common domain, i.e., πββ.
In practice, hydroelastic geometries themselves have a discrete representation: either a triangular surface mesh for rigid geometries or a tetrahedral volume mesh for compliant geometry. This discretization leads to contact surfaces that are likewise discrete.
Intersection between triangles and tetrahedra (or tetrahedra and tetrahedra) can produce polygons with up to eight sides. A ContactSurface can represent the resulting surface as a mesh of such polygons, or as a mesh of tesselated triangles. The domains of the two representations are identical. The triangular version admits for simple, highorder integration over the domain. Every element is a triangle, and triangles will only disappear and reappear as their areas go to zero. However, this increases the total number of faces in the mesh by more than a factor of three over the polygonal mesh. The polygonal representation produces fewer faces, but high order integration over polygons is problematic. We recommend choosing the cheapest representation that nevertheless supports your required fidelity (see QueryObject::ComputeContactSurfaces()).
The representation of any ContactSurface instance can be reported by calling representation(). If it returns HydroelasticContactRepresentation::kTriangle, then the mesh and pressure field can be accessed via tri_mesh_W() and tri_e_MN(), respectively. If it returns HydroelasticContactRepresentation::kPolygon, then use poly_mesh_W() and poly_e_MN().
Regardless of representation (polygon or triangle), the normal for each mesh face is guaranteed to point "out of" N and "into" M. They can be accessed via the mesh, e.g., tri_mesh_W().face_normal(face_index)
. By definition, the normals of the mesh are discontinuous at triangle boundaries.
The pressure values on the contact surface are represented as a continuous, piecewiselinear function, accessed via tri_e_MN() or poly_e_MN().
When available, the values of βeβ and βeβ are represented as a discontinuous, piecewiseconstant function over the faces – one gradient vector per face. These quantities are accessed via EvaluateGradE_M_W() and EvaluateGradE_N_W(), respectively.
For Point Q on the surface mesh of the contact surface between Geometry M and Geometry N, r_WQ = (x,y,z) is the displacement vector from the origin of the world frame to Q expressed in the coordinate frame of W. We also have the barycentric coordinates (b0, b1, b2) on a triangle of the surface mesh that contains Q. With vertices of the triangle labeled as vβ, vβ, vβ, we can map (b0, b1, b2) to r_WQ by:
r_WQ = b0 * r_Wvβ + b1 * r_Wvβ + b2 * r_Wvβ, b0 + b1 + b2 = 1, bα΅’ β [0,1],
where r_Wvα΅’ is the displacement vector of the vertex labeled as vα΅’ from the origin of the world frame, expressed in the world frame.
We use the barycentric coordinates to evaluate the field values.
T  The scalar type, which must be one of the default nonsymbolic scalars. 
#include <drake/geometry/query_results/contact_surface.h>
Public Member Functions  
ContactSurface (const ContactSurface &surface)  
ContactSurface &  operator= (const ContactSurface &surface)  
ContactSurface (ContactSurface &&)=default  
ContactSurface &  operator= (ContactSurface &&)=default  
GeometryId  id_M () const  
Returns the geometry id of Geometry M. More...  
GeometryId  id_N () const  
Returns the geometry id of Geometry N. More...  
bool  Equal (const ContactSurface< T > &surface) const  
Checks to see whether the given ContactSurface object is equal via deep exact comparison. More...  
Constructors  
The ContactSurface can be constructed with either a polygon or triangle mesh representation. The constructor invoked determines the representation. The general shape of each constructor is identical. They take the unique identifiers for the two geometries in contact, a mesh representation, a field representation, and (optional) gradients of the contacting geometries' pressure fields.
 
ContactSurface (GeometryId id_M, GeometryId id_N, std::unique_ptr< TriangleSurfaceMesh< T >> mesh_W, std::unique_ptr< TriangleSurfaceMeshFieldLinear< T, T >> e_MN, std::unique_ptr< std::vector< Vector3< T >>> grad_eM_W=nullptr, std::unique_ptr< std::vector< Vector3< T >>> grad_eN_W=nullptr)  
Constructs a ContactSurface with a triangle mesh representation. More...  
ContactSurface (GeometryId id_M, GeometryId id_N, std::unique_ptr< PolygonSurfaceMesh< T >> mesh_W, std::unique_ptr< PolygonSurfaceMeshFieldLinear< T, T >> e_MN, std::unique_ptr< std::vector< Vector3< T >>> grad_eM_W=nullptr, std::unique_ptr< std::vector< Vector3< T >>> grad_eN_W=nullptr)  
Constructs a ContactSurface with a polygonal mesh representation. More...  
Representationindependent API  
These methods represent sugar which masks the details of the mesh representation. They facilitate querying various mesh quantities that are common to the two representations, so that code can access the properties without worrying about the representation. If necessary, the actual meshes and fields can be accessed directly via the representationdependent APIs below.  
int  num_faces () const  
int  num_vertices () const  
const T &  area (int face_index) const  
const T &  total_area () const  
const Vector3< T > &  face_normal (int face_index) const  
Vector3< T >  centroid (int face_index) const  
const Vector3< T > &  centroid () const  
Representationdependent API  
These functions provide insight into what representation the ContactSurface instance uses, and provide access to the representationdependent quantities: mesh and field.  
bool  is_triangle () const  
Simpley reports if this contact surface's mesh representation is triangle. More...  
HydroelasticContactRepresentation  representation () const  
Reports the representation mode of this contact surface. More...  
const TriangleSurfaceMesh< T > &  tri_mesh_W () const  
Returns a reference to the triangular surface mesh whose vertex positions are measured and expressed in the world frame. More...  
const TriangleSurfaceMeshFieldLinear< T, T > &  tri_e_MN () const  
Returns a reference to the scalar field eββ for the triangle mesh. More...  
const PolygonSurfaceMesh< T > &  poly_mesh_W () const  
Returns a reference to the polygonal surface mesh whose vertex positions are measured and expressed in the world frame. More...  
const PolygonSurfaceMeshFieldLinear< T, T > &  poly_e_MN () const  
Returns a reference to the scalar field eββ for the polygonal mesh. More...  
Evaluation of constituent pressure fields  
The ContactSurface provisionally includes the gradients of the constituent pressure fields (βeβ and βeβ) sampled on the contact surface. In order for these values to be included in an instance, the gradient for the corresponding mesh must be well defined. For example a rigid mesh will not have a welldefined pressure gradient; as stiffness goes to infinity, the geometry becomes rigid and the gradient direction converges to the direction of the rigid mesh's surface normals, but the magnitude goes to infinity, producing a pressure gradient that would be some variant of Accessing the gradient values must be preconditioned on a test that the particular instance of ContactSurface actually contains the gradient data. The presence of gradient data for each geometry must be confirmed separately. The values βeβ and βeβ are piecewise constant over the ContactSurface and can only be evaluate on a perface basis.  
bool  HasGradE_M () const  
bool  HasGradE_N () const  
const Vector3< T > &  EvaluateGradE_M_W (int index) const  
Returns the value of βeβ for the face with index index . More...  
const Vector3< T > &  EvaluateGradE_N_W (int index) const  
Returns the value of βeβ for the face with index index . More...  
Friends  
template<typename U >  
class  ContactSurfaceTester 
ContactSurface  (  const ContactSurface< T > &  surface  ) 

default 
ContactSurface  (  GeometryId  id_M, 
GeometryId  id_N,  
std::unique_ptr< TriangleSurfaceMesh< T >>  mesh_W,  
std::unique_ptr< TriangleSurfaceMeshFieldLinear< T, T >>  e_MN,  
std::unique_ptr< std::vector< Vector3< T >>>  grad_eM_W = nullptr , 

std::unique_ptr< std::vector< Vector3< T >>>  grad_eN_W = nullptr 

) 
Constructs a ContactSurface with a triangle mesh representation.
ContactSurface  (  GeometryId  id_M, 
GeometryId  id_N,  
std::unique_ptr< PolygonSurfaceMesh< T >>  mesh_W,  
std::unique_ptr< PolygonSurfaceMeshFieldLinear< T, T >>  e_MN,  
std::unique_ptr< std::vector< Vector3< T >>>  grad_eM_W = nullptr , 

std::unique_ptr< std::vector< Vector3< T >>>  grad_eN_W = nullptr 

) 
Constructs a ContactSurface with a polygonal mesh representation.
const T& area  (  int  face_index  )  const 
const Vector3<T>& centroid  (  )  const 
bool Equal  (  const ContactSurface< T > &  surface  )  const 
Checks to see whether the given ContactSurface object is equal via deep exact comparison.
NaNs are treated as not equal as per the IEEE standard.
surface  The contact surface for comparison. 
true
if the given contact surface is equal. Returns the value of βeβ for the face with index index
.
std::exception  if HasGradE_M() returns false. 
index β [0, mesh().num_faces())
. Returns the value of βeβ for the face with index index
.
std::exception  if HasGradE_N() returns false. 
index β [0, mesh().num_faces())
. bool HasGradE_M  (  )  const 
true
if this
contains values for βeβ. bool HasGradE_N  (  )  const 
true
if this
contains values for βeβ. GeometryId id_M  (  )  const 
Returns the geometry id of Geometry M.
GeometryId id_N  (  )  const 
Returns the geometry id of Geometry N.
bool is_triangle  (  )  const 
Simpley reports if this contact surface's mesh representation is triangle.
Equivalent to:
representation() == HydroelasticContactRepresentation::kTriangle
and offered as convenient sugar.
int num_faces  (  )  const 
int num_vertices  (  )  const 
ContactSurface& operator=  (  const ContactSurface< T > &  surface  ) 

default 
const PolygonSurfaceMeshFieldLinear<T, T>& poly_e_MN  (  )  const 
Returns a reference to the scalar field eββ for the polygonal mesh.
is_triangle()
returns false
. const PolygonSurfaceMesh<T>& poly_mesh_W  (  )  const 
Returns a reference to the polygonal surface mesh whose vertex positions are measured and expressed in the world frame.
is_triangle()
returns false
. HydroelasticContactRepresentation representation  (  )  const 
Reports the representation mode of this contact surface.
If accessing the mesh or field directly, the APIs that can be successfully exercised are related to this methods return value. See below.
const T& total_area  (  )  const 
const TriangleSurfaceMeshFieldLinear<T, T>& tri_e_MN  (  )  const 
Returns a reference to the scalar field eββ for the triangle mesh.
is_triangle()
returns true
. const TriangleSurfaceMesh<T>& tri_mesh_W  (  )  const 
Returns a reference to the triangular surface mesh whose vertex positions are measured and expressed in the world frame.
is_triangle()
returns true
.

friend 