@@ -23,72 +23,59 @@ 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. 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.
26+ If ` distanceOrg < 0 ` , then the two objects are penetrating each other.
4527
4628Modia3D uses the dictionary ` contactDict ` to keep track of the
4729contact situation. Every pair of objects is identified by a unique
4830Integer value called * PairID* that is used as key in ` conctactDict ` .
4931A dictionary value is an instance of [ ` Modia3D.ContactPair ` ] ( @ref )
5032
5133At an ** event instant** (including initialization), dictionary ` contactDict ` is emptied
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.
34+ and all object pairs are stored newly in ` contactDict ` that have ` distanceOrg <= 0 ` , so are
35+ either touching or penetrating.
5536
5637During ** continuous integration** , two zero crossing functions are used:
5738
58- * `` z_1(t) `` : The maximum of ` distanceOrg+contact_eps ` of all object pairs that are in ` contactDict ` .
39+ * `` z_1(t) `` : The maximum of ` distanceOrg ` `` - 10^{-16} ` ` of all object pairs that are in ` contactDict ` .
5940 `` z_1 `` monitors if an object pair that has been in contact, looses contact.
60- Since penetration depth is in the order of `` 10^{-3} .. 10^{-6} ~m ``
41+ Since ` distanceOrg ` values in ` contactDict ` are in the order of `` 10^{-3} .. 10^{-6} ~m ``
6142 and ` eps(Float64) ` `` \approx 10^{-16} `` , a hysteresis epsilon must be larger as `` 10^{-19} .. 10^{-24} `` .
62- Actually, a hysteresis epsilon of `` 10^{-13 } `` is used. Note, it is guaranteed that
63- `` z_1 \le `` ` - contact_eps ` at event restart
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
6445 (when no contact pair is present, a dummy value is used).
6546
66- * `` z_2(t) `` : The minimum of ` distanceOrg+3*contact_eps ` of all object pairs that are ** not** in ` contactDict ` .
47+ * `` z_2(t) `` : The minimum ` distanceOrg ` of all object pairs that are ** not** in ` contactDict ` .
6748 `` z_2 `` monitors if two objects that have not been in contact to each other and start to penetrate each other.
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.
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.
7158
7259To summarize, the following equations are actually used:
7360
7461```
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>)
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>)
7966```
8067
8168Typically, the ` simulate!(..., log=true, ...) ` produces the following output (here for a sphere boucing on ground):
8269
8370```
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
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
9279```
9380
9481Whenever the integrator requires the values of the zero crossing functions, the values of
0 commit comments