@@ -23,59 +23,72 @@ otherwise a zero crossing cannot be detected.
2323
2424The distance between two objects computed either in the narrow phase or in an approximate
2525way in the broad phase (= distance between Axis Aligned Bounding Boxes) is called ` distanceOrg ` .
26- If ` distanceOrg < 0 ` , then the two objects are penetrating each other.
26+ If ` distanceOrg < 0 ` , then the two objects are penetrating each other. The crossing functions are
27+ formulated with the help of a hysteresis defined as:
28+
29+ ``` julia
30+ contact_eps = max (1e-13 , 10 * mprTolerance)
31+ ```
32+
33+ So it is in the order of `` 10^{-13} m `` , but at least a factor of 10 larger as the tolerance
34+ used for the distance computation with the MPR algorithm.
35+
36+ If the two shapes are treated in contact, the distance actually used for the elastic
37+ response calculation is
38+
39+ ```
40+ distance = distanceOrg + contact_eps
41+ ```
42+
43+ This means that penetration is assumed to occur at ` distanceOrg < -contact_eps ` , in order
44+ that there is by sure penetration, although ` distanceOrg ` is computed with some error.
2745
2846Modia3D uses the dictionary ` contactDict ` to keep track of the
2947contact situation. Every pair of objects is identified by a unique
3048Integer value called * PairID* that is used as key in ` conctactDict ` .
3149A dictionary value is an instance of [ ` Modia3D.ContactPair ` ] ( @ref )
3250
3351At an ** event instant** (including initialization), dictionary ` contactDict ` is emptied
34- and all object pairs are stored newly in ` contactDict ` that have ` distanceOrg <= 0 ` , so are
35- either touching or penetrating.
52+ and all object pairs are stored newly in ` contactDict ` that have ` distanceOrg < -2*contact_eps ` , so are
53+ penetrating already a bit. Note, this is useful, for example in case of a gripper, where it is natural that two shapes
54+ have a distance of zero and no contact situation is present.
3655
3756During ** continuous integration** , two zero crossing functions are used:
3857
39- * `` z_1(t) `` : The maximum of ` distanceOrg ` `` - 10^{-16} ` ` of all object pairs that are in ` contactDict ` .
58+ * `` z_1(t) `` : The maximum of ` distanceOrg+contact_eps ` of all object pairs that are in ` contactDict ` .
4059 `` z_1 `` monitors if an object pair that has been in contact, looses contact.
41- Since ` distanceOrg ` values in ` contactDict ` are in the order of `` 10^{-3} .. 10^{-6} ~m ``
60+ Since penetration depth is in the order of `` 10^{-3} .. 10^{-6} ~m ``
4261 and ` eps(Float64) ` `` \approx 10^{-16} `` , a hysteresis epsilon must be larger as `` 10^{-19} .. 10^{-24} `` .
43- Actually, a hysteresis epsilon of `` 10^{-16 } `` is used. Note, that in ` contactDict ` all ` distanceOrg ` values
44- are zero or negative at event restart. It is therefore guaranteed that `` z_1 \le - 10^{-16} ` ` at event restart
62+ Actually, a hysteresis epsilon of `` 10^{-13 } `` is used. Note, it is guaranteed that
63+ `` z_1 \le `` ` - contact_eps ` at event restart
4564 (when no contact pair is present, a dummy value is used).
4665
47- * `` z_2(t) `` : The minimum ` distanceOrg ` of all object pairs that are ** not** in ` contactDict ` .
66+ * `` z_2(t) `` : The minimum of ` distanceOrg+3*contact_eps ` of all object pairs that are ** not** in ` contactDict ` .
4867 `` z_2 `` monitors if two objects that have not been in contact to each other and start to penetrate each other.
49- At an event restart (including the start of the integration after the initialization), it is guaranteed
50- that all ` distanceOrg ` not in ` contactDict ` are positive (otherwise, they would be
51- in ` contactDict ` ). Therefore, it is guaranteed that `` z_2 > 0 `` at event restart (without a hysteresis epsilon).
52-
53- The distance between two objects is only computed up to a certain precision. Therefore, ` distanceOrg ` might be
54- nearly zero but still positive, if two objects are placed initially in touching position.
55- For this reason the actually used distance is ` distanceOrg - 1e-16 ` ,
56- in order that the probability is larger that objects initially in touching position
57- are treated to be in contact initially.
68+ At an event restart (including the start of the integration after the initialization),
69+ all contact pairs not in ` contactDict ` have `` z_2 > 0 `` (otherwise, they would be
70+ in ` contactDict ` ). Therefore, it is guaranteed that `` z_2 > 0 `` at event restart.
5871
5972To summarize, the following equations are actually used:
6073
6174```
62- distance = distanceOrg - 1e-16
63- contact = isEvent ? distance <= 0 : <contact from previous event>
64- z[1] = max(<distance that has contact=true>) - 1e-16
65- z[2] = min(<distance that has contact=false>)
75+ contact = isEvent ? distanceOrg < -2*contact_eps : <contact from last event>
76+ distance = contact ? distanceOrg + contact_eps : distanceOrg + 3*contact_eps
77+ z[1] = max(<distanceOrg+contact_eps that has contact=true>)
78+ z[2] = min(<distanceOrg+3*contact_eps that has contact=false>)
6679```
6780
6881Typically, the ` simulate!(..., log=true, ...) ` produces the following output (here for a sphere boucing on ground):
6982
7083```
71- State event (zero-crossing) at time = 2.3924142776549155 s (due to z[2])
72- distance(ground,sphere) = -3.815173674537923e-18 became <= 0
73- contact normal = [0.0, 1.0, 0.0], contact position = [0.0, -0.1, 0.0], c_res = 1.1e11 d_res = 47.5
74- restart = Restart
75-
76- State event (zero-crossing) at time = 2.3924413895015424 s (due to z[1])
77- distance(ground,sphere) = 1.0362163563391329e-16 became > 0
78- restart = Restart
84+ State event (zero-crossing) at time = 2.3850903177319287 s (due to z[2])
85+ distance(ground,sphere) = -2.0001204970840633e-13 became <= 0
86+ contact normal = [0.0, 1.0, 0.0], contact position = [0.0, -0.1, 0.0], c_res = 1.1e11 d_res = 22.0
87+ restart = Restart
88+
89+ State event (zero-crossing) at time = 2.3851135168512942 s (due to z[1])
90+ distance(ground,sphere) = 3.1358549064074168e-18 became > 0
91+ restart = Restart
7992```
8093
8194Whenever the integrator requires the values of the zero crossing functions, the values of
0 commit comments