ObjectContactFrictionCircleCable2D
A very specialized penalty-based contact/friction condition between a 2D circle in the local x/y plane (=marker0, a RigidBody Marker, from node or object) on a body and an ANCFCable2DShape (=marker1, Marker: BodyCable2DShape), in xy-plane; a node NodeGenericData is required with 3\(\times\)(number of contact segments) – containing per segment: [contact gap, stick/slip (stick=0, slip=+-1, undefined=-2), last friction position]. The connector works with Cable2D and ALECable2D, HOWEVER, due to conceptual differences the (tangential) frictionStiffness cannot be used with ALECable2D; if using, it gives wrong tangential stresses, even though it may work in general.
Additional information for ObjectContactFrictionCircleCable2D:
- This
Object
has/provides the following types =Connector
- Requested
Marker
type =_None
- Requested
Node
type =GenericData
The item ObjectContactFrictionCircleCable2D with type = ‘ContactFrictionCircleCable2D’ has the following parameters:
- name [type = String, default = ‘’]:connector’s unique name
- markerNumbers [\([m0,m1]\tp\), type = ArrayMarkerIndex, default = [ invalid [-1], invalid [-1] ]]:a marker \(m0\) with position and orientation and a marker \(m1\) of type BodyCable2DShape; together defining the contact geometry
- nodeNumber [\(n_g\), type = NodeIndex, default = invalid (-1)]:node number of a NodeGenericData with 3 \(\times n_{cs}\) dataCoordinates (used for active set strategy \(\ra\) hold the gap of the last discontinuous iteration, friction state (+-1=slip, 0=stick, -2=undefined) and the last sticking position; initialize coordinates with list [0.1]*\(n_{cs}\)+[-2]*\(n_{cs}\)+[0.]*\(n_{cs}\), meaning that there is no initial contact with undefined slip/stick
- numberOfContactSegments [\(n_{cs}\), type = PInt, default = 3]:number of linear contact segments to determine contact; each segment is a line and is associated to a data (history) variable; must be same as in according marker
- contactStiffness [\(k_c\), type = UReal, default = 0.]:contact (penalty) stiffness [SI:N/m/(contact segment)]; the stiffness is per contact segment; specific contact forces (per length) \(f_n\) act in contact normal direction only upon penetration
- contactDamping [\(d_c\), type = UReal, default = 0.]:contact damping [SI:N/(m s)/(contact segment)]; the damping is per contact segment; acts in contact normal direction only upon penetration
- frictionVelocityPenalty [\(\mu_v\), type = UReal, default = 0.]:tangential velocity dependent penalty coefficient for friction [SI:N/(m s)/(contact segment)]; the coefficient causes tangential (contact) forces against relative tangential velocities in the contact area
- frictionStiffness [\(\mu_k\), type = UReal, default = 0.]:tangential displacement dependent penalty/stiffness coefficient for friction [SI:N/m/(contact segment)]; the coefficient causes tangential (contact) forces against relative tangential displacements in the contact area
- frictionCoefficient [\(\mu\), type = UReal, default = 0.]:friction coefficient [SI: 1]; tangential specific friction forces (per length) \(f_t\) must fulfill the condition \(f_t \le \mu f_n\)
- circleRadius [\(r\), type = UReal, default = 0.]:radius [SI:m] of contact circle
- useSegmentNormals [type = Bool, default = True]:True: use normal and tangent according to linear segment; this is appropriate for very long (compared to circle) segments; False: use normals at segment points according to vector to circle center; this is more consistent for short segments, as forces are only applied in beam tangent and normal direction
- activeConnector [type = Bool, default = True]:flag, which determines, if the connector is active; used to deactivate (temporarily) a connector or constraint
- visualization [type = VObjectContactFrictionCircleCable2D]:parameters for visualization of item
The item VObjectContactFrictionCircleCable2D has the following parameters:
- show [type = Bool, default = True]:set True, if item is shown in visualization and false if it is not shown; note that only normal contact forces can be drawn, which are approximated by \(k_c \cdot g\) (neglecting damping term)
- showContactCircle [type = Bool, default = True]:if True and show=True, the underlying contact circle is shown; uses circleTiling*4 for tiling (from VisualizationSettings.general)
- drawSize [type = float, default = -1.]:drawing size = diameter of spring; size == -1.f means that default connector size is used
- color [type = Float4, default = [-1.,-1.,-1.,-1.]]:RGBA connector color; if R==-1, use default color
DESCRIPTION of ObjectContactFrictionCircleCable2D
The following output variables are available as OutputVariableType in sensors, Get…Output() and other functions:
Coordinates
: \([u_{t,0},\, g_0,\, u_{t,1},\, g_1,\, \ldots,\, u_{t,n_{cs}},\, g_{n_{cs}}]\tp\)local (relative) displacement in tangential (\({\mathbf{t}}\)) and normal (\({\mathbf{n}}\)) direction per segment (\(n_{cs}\)); values are only provided in case of contact, otherwise zero; tangential displacement is only non-zero in case of sticking!Coordinates\_t
: \([v_{t,0},\, v_{n,0},\, v_{t,1},\, v_{n,1},\, \ldots,\, v_{t,n_{cs}},\, v_{n,n_{cs}}]\tp\)local (relative) velocity in tangential (\({\mathbf{t}}\)) and normal (\({\mathbf{n}}\)) direction per segment (\(n_{cs}\)); values are only provided in case of contact, otherwise zeroForceLocal
: \([f_{t,0},\, f_{n,0},\, f_{t,1},\, f_{n,1},\, \ldots,\, f_{t,n_{cs}},\, f_{n,n_{cs}}]\tp\)local contact forces in tangential (\({\mathbf{t}}\)) and normal (\({\mathbf{n}}\)) direction per segment (\(n_{cs}\))
Definition of quantities
intermediate variables
|
symbol
|
description
|
---|---|---|
marker m0 position
|
\(\LU{0}{{\mathbf{p}}}_{m0}\)
|
represents current global position of the circle’s centerpoint
|
marker m0 velocity
|
\(\LU{0}{{\mathbf{v}}}_{m0}\)
|
current global velocity which is provided by marker m0
|
marker m1
|
represents the 2D ANCF cable
|
|
data node
|
\({\mathbf{x}}=[x_{i},\; \ldots,\; x_{3 n_{cs} -1}]\tp\)
|
coordinates of node with node number \(n_{GD}\)
|
data coordinates for segment \(i\)
|
\([x_i,\, x_{n_{cs}+ i},\, x_{2\cdot n_{cs}+ i}]\tp = [x_{gap},\, x_{isSlipStick},\, x_{lastStick}]\tp\), with \(i \in [0,n_{cs}-1]\)
|
The data coordinates include the gap \(x_{gap}\), the stick-slip state \(x_{isSlipStick}\) and the previous sticking position \(x_{lastStick}\) as computed in the PostNewtonStep, see description below.
|
shortest distance to segment \(s_i\)
|
\({\mathbf{d}}_{g,i}\)
|
shortest distance of center of circle to contact segment, considering the endpoint of the segment
|
Connector forces: contact geometry
The connector represents a force element between a ‘circle’ (or cylinder) represented by a marker \(m0\), which has position and orientation,
and an ANCFCable2D
beam element (denoted as ‘cable’) represented by a MarkerBodyCable2DShape
\(m1\).
The cable with reference length \(L\) is discretized by splitting into \(n_{cs}\) straight segments \(s_i\), located between points \(p_i\) and \(p_{i+1}\).
Note that these points can be placed with an offset from the cable centerline, see verticalOffset
defined in MarkerBodyCable2DShape
.
In order to compute the gap function for a line segment, the shortest distance of one line segment with
points \({\mathbf{p}}_i\), \({\mathbf{p}}_{i+1}\) to the circle’s centerpoint given by the marker \({\mathbf{p}}_{m0}\) is computed.
All computations here are performed in the global coordinates system (0),
including edge points of every segment.
With the intermediate quantities (all of them related to segment \(s_i\))(we omit \(s_i\) in some terms for brevity!),
and assuming that \(d \neq 0\) (otherwise the two segment points would be identical and the shortest distance would be \(d_g = |{\mathbf{v}}_p|\)), we find the relative position \(\rho\) of the shortest (projected) point on the segment, which runs from 0 to 1 if lying on the segment, as
We distinguish 3 cases (see also Fig. 43 for cases 1 and 2):
- If \(\rho \le 0\), the shortest distance would be the distance to point \({\mathbf{p}}_p={\mathbf{p}}_i\),
reading
- If \(\rho \ge 1\), the shortest distance would be the distance to point \({\mathbf{p}}_p={\mathbf{p}}_{i+1}\),
reading
- Finally, if \(0 < \rho < 1\), then the shortest distance has a projected point somewhere
on the segment with the point (projected on the segment)
Here, the shortest distance vector for every segment results from the projected point \({\mathbf{p}}_p\)of the above mentioned cases, see also Fig. 43, with the relation
The contact gap for a specific point for segment \(s_i\) is in general defined as
using \(d_g = |{\mathbf{d}}_g|\).
Contact frame and relative motion
Irrespective of the choice of useSegmentNormals
, the contact normal vector \({\mathbf{n}}_{s_i}\) and tangential vector \({\mathbf{t}}_{s_i}\) are defined per segment as
The vectors \({\mathbf{t}}_{s_i}\) and \({\mathbf{n}}_{s_i}\) define the local (contact) frame for further computations.
The velocity at the closest point of the segment \(s_i\) is interpolated using \(\rho\) and computed as
Alternatively, \(\dot {\mathbf{p}}_p\) could be computed from the cable element by evaluating the velocity at the contact points, but we feel that this choice is more consistent with the computations at position level.
The gap velocity \(v_n\) (\(\neq \dot g\)) thus reads
In a similar, the tangential velocity reads
In case of frictionStiffness != 0
, we continuously track the sticking position at which the cable element (or segment) and the circle
previously sticked together, similar as proposed by Lugr{'i}s et al.~.
The difference here to the latter reference, is that we explicitly exclude switching from Newton’s method and that Lugr{'i}s et al.~used
contact points, while we use linear segments.
For a simple 1D example using this position based approach for friction, see Examples/lugreFrictionText.py
,
which compares the traditional LuGre friction model with the position based model with tangential stiffness.
Because there is the chance to wind/unwind relative to the (last) sticking position without slipping, the following strategy is used. In case of sliding (which could be the last time sliding before sticking), we compute the current sticking position, see Fig. 44, as the sum of the relative position at the segment \(s\)
in which \(\rho \in [0,1]\) denotes the relative position of contact at the segment with reference length \(L_{seg}=\frac{L}{n_{cs}}\). The relative position at the circle \(c\) is
We immediately see, that under pure rolling(neglecting the effects of small penetration, usually much smaller than shown for visibility in Fig. 44.),
Note that the verticalOffset
from the cable center line, as defined in the related MarkerBodyCable2DShape
,
influences the behavior significantly, which is why we recommend to use verticalOffset=0
whenever this is an
appropriate assumption.
Thus, the current sticking position \(x_{curStick}\) is computed per segment as
Due to the possibility of switching of \(\alpha+\phi\) between \(-\pi\) and \(\pi\), the result is normalized to
which gives \(\bar x_{curStick} \in [-\pi \cdot r,\pi \cdot r]\), which is stored in the 3rd data variable (per segment).
The function floor() is a standardized version of rounding, available in C and Python programming languages.
In the PostNewtonStep
, the last sticking position is computed, \(x_{lastStick} = x_{curStick}\), and it is also available in the startOfStep
state.
Contact forces: definition
The contact force \(f_n\) is zero for \(g > 0\) and otherwise computed from
NOTE that currently, there is only a linear spring-damper model available, assuming that the impact dynamics is not dominating (such as in belt drives or reeving systems).
Friction forces are primarily based on relative (tangential) velocity at each segment. The ‘linear’ friction force, based on the velocity penalty parameter \(\mu_v\) reads
PostNewtonStep
In general, see the solver flow chart for the DiscontinuousIteration
, see Fig. 34, should be considered when reading this description. Every step is started with values startOfStep
, while current values are iterated and updated in the Newton or DiscontinuousIteration
.
The PostNewtonStep
computes 3 values per segment, which are used for computation of contact forces, irrespectively of the
current geometryof the contact.
The PostNewtonStep
is called after every full Newton method and evaluates the current state w.r.t. the assumed data variables.
If the assumptions do not fit, new data variables are computed.
This is necessary in order to avoid discontinuities in the equations, while otherwise the Newton iterations would not
(or only slowly) converge.
The data variables per segment are
Here, \(x_{gap}\) contains the gap of the segment (\(\le 0\) means contact), \(x_{lastStick}\) is described in Eq. (82), and \(x_{isSlipStick}\) defines the stick or slip case,
\(x_{isSlipStick} = -2\): undefined, used for initialization
\(x_{isSlipStick} = 0\): sticking
\(x_{isSlipStick} = \pm 1\): slipping, sign defines slipping direction
The basic algorithm in the PostNewtonStep
, with all operations given for any segment \(s_i\), can be summarized as follows:
- [I.] Evaluate gap per segment \(g\) using Eq. (79) and store in data variable:
\(x_{gap} = g\)
[II.] If \(x_{gap} < 0\) and (\(\mu_v \neq 0\) or \(\mu_k \neq 0\)):
Compute contact force \(f_n\) according to Eq. (83)
Compute current sticking position \(x_{curStick}\) according to Eq. (81)(terms are only evaluated if \(\mu_k \neq 0\))
- Retrieve
startOfStep
sticking position(Importantly, thePostNewtonStep
always refers to thestartOfStep
state in the sticking position, because in the discontinuous iterations, the algorithm could switch to slipping in between and override the last sticking position in the current step) in \(x^{startOfStep}_{lastStick}\) and compute and normalize difference in sticking position(in case that \(x_{isSlipStick} = -2\), meaning that there is no stored sticking position, we set \(\Delta x_{stick} = 0\)):
- Retrieve
Compute linear tangential force for friction stiffness and velocity penalty:
- Compute tangential force according to Coulomb friction model (note that the sign of \(\Delta x_{stick}\) is used here, but
alternatively we may also use the sign of \(f_{t,lin}\)):
- In the case of slipping, given by \(|f_t^{(lin)}| > \mu \cdot |f_n|\), we update the last sticking position in the data variable,
such that the spring is pre-tensioned already,
- In the case of sticking, given by \(|f_t^{(lin)}| \le \mu \cdot |f_n|\)Set \(x_{isSlipStick} = 0\) and,
if \(x^{startOfStep}_{isSlipStick} = -2\) (undefined), we update \(x_{lastStick} = x_{curStick}\), while otherwise, \(x_{lastStick}\) is unchanged.
[III. ] If \(x_{gap} > 0\) or (\(\mu_v == 0\) and \(\mu_k == 0\)), we set \(x_{isSlipStick} = -2\) (undefined); this means that in the next step (if this step is accepted), there is no stored sticking position.
- [IV.] Compute an error \(\varepsilon_{PNS} = \varepsilon^n_{PNS}+\varepsilon^t_{PNS}\),
with physical units forces (per segment point), for
PostNewtonStep
:
if gap \(x_{gap,lastPNS}\) of previous
PostNewtonStep
had different sign to current gap, set
while otherwise \(\varepsilon^n_{PNS}=0\).
+ if stick-slip-state \(x_{isSlipStick,lastPNS}\) of previous PostNewtonStep
is different from current \(x_{isSlipStick}\), set
while otherwise \(\varepsilon^t_{PNS}=0\).
Note that the PostNewtonStep
is iterated and the data variables are updated continuously until convergence, or until a max.number of iterations is reached. If ignoreMaxIterations
== 0, computation will continue even if no convergence is reached after the given number of iterations. This will lead so larger errors in such steps, but may have less influence on the overall solution if such cases are rare.
Computation of connector forces in Newton
The computation of LHS terms, the action of forces produced by the contact-friction element, is done during Newton iterations and may not have
discontinuous behavior, thus relating computations to data variables computed in the PostNewtonStep
.
For efficiency, the LHS computation is only performed, if the PostNewtonStep
determined contact in any segment.
The operations are similar to the PostNewtonStep
, but without switching. The following operations are performed for each segment \(s_i\), if
\(x_{gap, s_i} <= 0\):
[I.] Compute contact force \(f_n\), Eq. (83).
[II.] In case of sticking (\(|x_{isSlipStick}|\neq 1\)):
[II.1] the current sticking position \(x_{curStick}\) is computed from Eq. (81), and the difference of current and last sticking position reads(see the difference to the
PostNewtonStep
: we use \(x_{lastStick}\) here, not thestartOfStep
variant.):
[II.2] if the friction stiffness is \(\mu_k==0\) or if \(x_{isSlipStick} == -2\), we set \(\Delta x_{stick}=0\)
[II.3] using the tangential velocity from Eq. (80), the tangent force follows as (even if it is larger than the sticking limit)
[III.] In case of slipping (\(|x_{isSlipStick}|=1\)), the tangential firction force is set as(see again difference to
PostNewtonStep
!),
Note that in the Newton method, the tangential force may be inconsistent with the Kuhn-Tucker conditions. However,
the PostNewtonStep
resolves this inconsistency.
Computation of LHS terms for circle and ANCF cable element
If activeConnector = True
,
contact forces \({\mathbf{f}}_i\) with \(i \in [0,n_{cs}]\) – these are \((n_{cs}+1)\) forces – are applied at the points \(p_i\), and they are computed for every contact segments (i.e., two segments may contribute to contact forces of one point).
For every contact computation, first all contact forces at segment points are set to zero.
We distinguish two cases SN and PWN. If useSegmentNormals==True
, we use the SN case, while otherwise the PWN case is used,
compare Fig. 45.
Segment normals (=SN) lead to always good approximations for normal directions, irrespectively of short or extremely long segments as compared to the circle. However, in case of segments that are short as compared to the circle radius, normals computed from the center of the circle to the segment points (=PWN) are more consistent and produce tangents only in circumferential direction, which may improve behavior in some applications. The equations for the two cases read:
CASE SN: use Segment Normals
If there is contact in a segment \(s_i\), i.e., gap state \(x_{gap} \le 0\), see Fig. 43(right), contact forces \({\mathbf{f}}_{s_i}\) are computed per segment,
and added to every force at segment points according to
- while in case \(x_{gap} > 0\) nothing is added.
CASE PWN: use Point Wise Normals (at segment points)
If there is contact in a segment \(s_i\), i.e., gap \(x_{gap} \le 0\), see Fig. 43(right), intermediate contact forces \({\mathbf{f}}^{l,r}_{i}\) are computed per segment point,
while in case \(x_{gap} > 0\) nothing is added.
The forces \({\mathbf{f}}_i\) are then applied through the marker to the ObjectANCFCable2D
element as point loads via a position jacobian
(using the according access function), for details see the C++ implementation.
The forces on the circle marker \(m0\) are computed as the total sum of all segment contact forces,
and additional torques on the circle’s rotation simply follow from
During Newton iterations, the contact forces for segment \(s_i\) are considered only, if \(x_i <= 0\). The dataCoordinate \(x_i\) is not modified during Newton iterations, but computed during the DiscontinuousIteration, see Fig. 34 in the solver description.
If activeConnector = False
, all contact and friction forces on the cable and the force and torque on the
circle’s marker are set to zero.
Relevant Examples and TestModels with weblink:
beltDriveALE.py (Examples/), beltDriveReevingSystem.py (Examples/), beltDrivesComparison.py (Examples/), sliderCrank3DwithANCFbeltDrive.py (Examples/), sliderCrank3DwithANCFbeltDrive2.py (Examples/), ANCFcontactFrictionTest.py (TestModels/), ANCFmovingRigidBodyTest.py (TestModels/), ANCFslidingAndALEjointTest.py (TestModels/)
The web version may not be complete. For details, consider also the Exudyn PDF documentation : theDoc.pdf