ObjectContactCurveCircles

A contact model between a curve defined by piecewise segments and a set of circles. The 2D curve may corotate in 3D with the underlying marker and also defines the plane of action for the circles. [REQUIRES FURTHER TESTING]

Interface

Parameters

The parameters of the item; in a dictionary, its type is ‘ContactCurveCircles’:

name

type

size

default

description

name

String

‘’

constraints’s unique name

markerNumbers

ArrayMarkerIndex

2

[ invalid (-1), invalid (-1) ]

(symbol: \([m0,m_{c0},m_{c1},\ldots]\tp\)) list of \(n_c+1\) markers; marker \(m0\) represents the marker carrying the curve; all other markers represent centers of \(n_c\) circles, used in connector

nodeNumber

NodeIndex

invalid (-1)

(symbol: \(n_d\)) node number of a NodeGenericData with nDataVariablesPerSegment dataCoordinates per segment, needed for discontinuous iteration; data variables contain values from last PostNewton iteration: data[0+3i] is the circle number, data[1+3i] is the gap, data[2+3*i] is the tangential velocity (and thus contains information if it is stick or slip)

circlesRadii

NumpyVector

[]

(symbol: \([r_{c0},r_{c1}, \ldots]\tp \in \Rcal^{n_c}\)) Vector containing radii of \(n_c\) circles [SI:m]; number according to size of markerNumbers-1

segmentsData

PyMatrixContainer

[]

(symbol: \(\Dm \in \Rcal^{n_s \times 4}\)) matrix containing a set of two planar point coordinates in each row, representing segments attached to marker \(m0\) and undergoing contact with the circles; for segment \(s0\) row 0 reads \([p_{0x,s0},\,p_{0y,s0},\,p_{1x,s0},\,p_{1y,s0}]\); note that the segments must be ordered such that going from \(\pv_0\) to \(\pv_1\), the exterior lies on the right (positive) side. MatrixContainer has to be provided in dense mode!

polynomialData

PyMatrixContainer

[]

(symbol: \(\Pm \in \Rcal^{n_s \times n_p}\)) matrix containing coefficients for special polynomial enhancements of the linear segments; each row contains coefficients for polynomials for the according segment, prescribing slopes at beginning and end of segment as well as curvature at beginning and end of segment; slopes and curvatures are defined in a local x/y coordinate system where x is the segment axis (start: x=0; x-axis points towards end point) and the segment normal is in y-direction; MatrixContainer has to be provided in dense mode!

dynamicFriction

UReal

0.

(symbol: \(\mu_d\)) dynamic friction coefficient: the friction force is \(\mu_d \vert f_N\vert \), regularized below frictionProportionalZone, see the equation; 0: no friction

frictionProportionalZone

UReal

0.001

(symbol: \(v_{reg}\)) limit velocity [SI:m/s] up to which the friction force is proportional to the tangential velocity (regularization, against numerical oscillations); 0: no regularization

contactStiffness

Real

0.

(symbol: \(k_c\)) normal contact stiffness [SI:N/(m*m)]

contactDamping

Real

0.

(symbol: \(d_c\)) linear normal contact damping [SI:N/(m s)]; this damping is a simplification of real contact dissipation and should be used with care.

contactModel

UInt

0

(symbol: \(m_\mathrm{contact}\)) number of contact model: 0) linear model for stiffness and damping, only proportional to penetration; contact force is computed from \(l_\mathrm{seg}\left(p \cdot \cdot k_c + \dot p \cdot d_c \right)\) as long as \(p>0\); while this is numerically more stable, it gives jumps in forces when sliding over contact geometry 1) contact force proportional to integral over penetration area of circle with segments, giving a smoother contact force when sliding over geometry;

activeConnector

Bool

True

flag, which determines, if the connector is active; used to deactivate (temporarily) a connector or constraint

gapPerSegment

NumpyVector

[]

temporary vector for computed gap

gapPerSegment_t

NumpyVector

[]

temporary vector for computed gap velocity

segmentsForceLocalX

NumpyVector

[]

temporary vector for contact force per segment in local X-direction

segmentsForceLocalY

NumpyVector

[]

temporary vector for contact force per segment in local Y-direction

visualization

VObjectContactCurveCircles

parameters for visualization of item

Visualization parameters

The parameters of VObjectContactCurveCircles, given as visualization:

name

type

size

default

description

show

Bool

True

set true, if item is shown in visualization and false if it is not shown; draws curve and circles with given radii; uses visualizationSettings circleTiling for circles and circleTiling/2 for tiling of non-straight segments

color

Float4

4

[-1.,-1.,-1.,-1.]

RGBA connector color; if R==-1, use default color

Drawing

Drawn as all connectors; with connectors.showContact, the curve as lines with points at its segments, and the circles of the markers with general.circleTiling segments.

Settings beyond those of all connectors: connectors.showContact, contact.contactPointsDefaultSize, contact.tilingCurves, general.circleTiling, general.sphereTiling.

Output variables

Available as OutputVariableType in sensors, Get...Output() and other functions:

output variable

symbol

description

DisplacementLocal

\([g_0,\,g_1,\,\ldots]\tp\)

per segment, the gap of the circle closest to it (< 0: penetration), from the current configuration; the largest float if there is no circle

VelocityLocal

\([\dot g_0,\,\dot g_1,\,\ldots]\tp\)

per segment, the normal relative velocity of that circle

ForceLocal

\([f_{x,0},\,f_{y,0},\,f_{x,1},\,\ldots]\tp\)

per segment, the contact force - normal and friction - on the circle in contact with it, in the frame of marker m0, with the contact states of the data node; zero without contact

Detailed description

Further testing is required, as the class description says.

Definition of quantities

intermediate variables

symbol

description

marker m0 position, orientation

\(\LU{0}{\pv}_{m0}\), \(\LU{0,m0}{\Rot}\)

the frame carrying the curve, which lies in its \(x\)-\(y\) plane; a rotation of it is given to the marker as its localHT

circle markers

\(\LU{0}{\pv}_{c_i}\)

centers of the \(n_c\) circles with radii circlesRadii

segments

\(\Dm\)

segmentsData: one straight segment per row, two planar points in the curve frame

polynomials

\(\Pm\)

polynomialData: optional coefficients that bend each segment in the drawing only; the contact does not use them, it uses the straight segments

data coordinates

\(\xv\)

per segment, the state of the last post Newton step

Geometric relations

The circle centers are transformed into the frame of the curve and projected into its plane. For each segment and each circle, the gap is the distance of the circle center from the segment minus the radius; a segment takes the circle with the largest penetration. The penetration is integrated along the part of the segment in contact, so that the contact stiffness does not depend on how finely the curve is divided.

Connector forces

Per segment in contact, the normal force follows from contactStiffness, contactDamping and the integrated penetration, as contactModel selects; it acts in the plane of the curve on the circle center and, with opposite sign, on marker 0 with the torque of its lever arm. A segment must be short enough that only one circle touches it at a time, which the connector warns about.

With dynamicFriction \(\mu_d > 0\), a friction force acts in the tangential direction \(\tv\) of the contact, against the tangential relative velocity \(v_t\) of the circle center against the curve,

\[ f_t = -\mu_d\, |f_N|\, \frac{v_t}{v_{reg}} \;\; \mathrm{for} \;\; |v_t| < v_{reg}, \quad f_t = -\mu_d\, |f_N|\, \mathrm{sign}(v_t) \;\; \mathrm{otherwise}, \]

with frictionProportionalZone \(v_{reg}\) (0: no regularization); there is no sticking state.

Mini example

#a planar body with a circle of radius 0.1 resting on a curve of line segments (the ground line y=0)
node = mbs.AddNode(NodeRigidBody2D(referenceCoordinates=[0,0.1,0]))
body = mbs.AddObject(ObjectRigidBody2D(nodeNumber=node, mass=1, inertia=0.01))
mbs.AddLoad(LoadForceVector(markerNumber=mbs.AddMarker(MarkerBodyPosition(bodyNumber=body)), loadVector=[0,-10,0]))
mCurve = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oGround, localPosition=[0,0,0]))
mCircle = mbs.AddMarker(MarkerBodyRigid(bodyNumber=body, localPosition=[0,0,0]))
segments = np.array([[1,0, -1,0]]) #one segment [x0,y0, x1,y1]; the contact side is to the left of 1->0
nData = mbs.AddNode(NodeGenericData(numberOfDataCoordinates=3, initialCoordinates=[-1,0,0]))
mbs.AddObject(ObjectContactCurveCircles(markerNumbers=[mCurve, mCircle], nodeNumber=nData, circlesRadii=[0.1],
                                        segmentsData=exu.MatrixContainer(segments),
                                        contactStiffness=1e4, contactDamping=100))

mbs.Assemble()
mbs.SolveDynamic()

#at rest: 0.1 - F/k
exu.sys['testResult'] = mbs.GetNodeOutput(node, exu.OutputVariableType.Position)[1] #0.099

Relevant Examples (Ex) and TestModels (TM) with weblink to github: camFollowerExample.py (Ex), chainDriveExample.py (Ex), contactCurvePolynomial.py (Ex), contactCurveWithLongCurve.py (Ex), contactCurveCirclesFrictionTest.py (TM), contactCurveExample.py (TM)