Resting Contacts

advertisement
3.6. RESTING CONTACTS AND FRICTION
Exploration of resting contacts and friction
Resolving a set of contacts
Resting Forces
A resting contact is a type of contact where the objects involved are
moving neither apart nor together.
In this case they need to be kept apart while making sure each object
behaves normally using Newton’s Third Law of Motion: “For every action
there is an equal and opposite reaction.”
In other words, an object resting on the ground is subject to a gravitational
force, pushing the object down, and an equal upwards reaction force from
the ground preventing the object from moving down.
Resting Forces
Resting contacts could be handled by
calculating the reaction forces and
adding these into the overall mix of
applied forces (using D’Alembert’s
principle). This requires a global
approach for contact resolution and
becomes considerably more complex
as the number of resting contacts
between bodies increases.
Whilst the above approach is more
accurate (and adopted within industry
strength packages) a less complex (and
less accurate) solution can also be
used: resting contacts are treated in
terms of a series of micro-collisions.
Micro-collisions
Micro-collisions replace reaction forces by a series of impulses: one per
update (i.e. the resting force is modelled as a series of impulses)
Modelling a resting contact as a series of impulses may be problematic as,
depending on the restitution, resolving the downwards motion may produce
upwards motion - resulting in mini-bounces, i.e. jitter. This problem can be
(mostly) overcome by:
•
•
Removing any velocity built up from acceleration in the previous update.
Decrease the coefficient of restitution for collisions with very low speeds.
Micro-collisions: Removing Accelerative Velocity
Removing velocity due to accelerative forces
By tracking the acceleration at each rigid body update (only linear
acceleration need be stored as most reaction forces arise from gravity –
which is a linear acceleration), it becomes possible to calculate the desired
change in velocity for a contact (Stage 4 of the Velocity Resolution
algorithm) by subtracting the acceleration-induced velocity in the direction
of the contact normal, vacc, ie. (where vs is the separating velocity and c is
the coefficient of restitution):
Micro-collisions: Lowering the Restitution
A complementary approach to removing the effects of gravity acceleration
is to also reduce the restitution of contacts involving very low closing
velocities (thereby dampening all low speed contacts).
This can be simply accomplished as:
float appliedRestitution =
contactVelocity.magnitude() < velocityLimit
? 0.0f : restitution;
Introducing friction
Types of Friction
Friction is the force generated when one object moves or tries to move in
contact with another.
There are two forms of friction: static and dynamic.
Types of Friction: Static Friction
Static friction is a force that stops an object from moving when it is
stationary and depends on the materials in contact and the reaction force:
where fstatic is the friction force generated, μstatic is the coefficient of static
friction (an empirical material-pair property) and r is the reaction force in
the direction of the contact normal (given by
where d is the
contact normal and f is the total force exerted).
As more force is exerted, static friction
pushes back until the limit of static
friction (μstatic|r|) is reached. A force
beyond this limit may result in object
movement, a sudden drop in the
opposing frictional force, and the
introduction of dynamic friction.
Types of Friction: Dynamic Friction
Dynamic (or kinetic) friction behaves like static friction but has a different
coefficient of friction and can be defined as (where μdynamic is the
coefficient of dynamic friction, and vplanar is movement velocity along the
plane).
Rather than acting in the opposite direction to the
planar force (as for static friction), dynamic friction
acts in the opposite direction to the object velocity
(thereby acting to slow down and stop the object
even if the applied moving force is removed).
Within game physics, both types of friction are
generally combined into a single model, with a
single coefficient of friction.
Types of Friction: Isotropic and Anisotropic
Friction across a surface may be either isotropic or anisotropic. Isotropic
friction has the same coefficient in all directions. Anisotropic friction can
have different coefficients in different directions.
Typically game engines are only concerned with modelling isotropic
friction (or only support a simple anisotropic model of friction).
Implementing Friction
As an impulse-based approach using micro-collisions for resting contacts
has been assumed, it will be necessary to implement friction within this
framework (an approximation as resting forces are not calculated) Within a
force based physics engine, friction would be introduced into the mix as
another type of force.
Friction as Impulses
Given a contact, the velocity of the object is adjusted in the direction of the
contact normal. By extending this approach to include the remaining two
contact directions (i.e. representing directions in the plane of the contact)
we have a means of introducing static and dynamic friction, i.e. the change
in velocity now includes:
Vector3 deltaVelocityVector(
velocityChangeAlongCollisionNormal,
contactVelocityAlongYAxis, contactVelocityAlongZAxis);
Implementing Friction
In order to calculate the maximum amount of planar velocity that can be
removed (representing the limit of static friction) we use the relationship
between velocity and impulse (where g is the impulse and m the mass):
The normal reaction force can be approximately calculated from using the
amount of velocity to be removed in the direction of the contact normal.
Assuming Δv is the change in velocity the reaction force is approximated
as:
Hence, the maximum frictional impulse that should be applied is:
Where Δgnormal is the impulse in the direction of the contact normal (i.e. the
impulse which is currently calculated to resolve contact velocity)
Implementing Friction
Dynamic friction can be handled by scaling the y and z (i.e. planar)
components of the impulse so that their combined size is exactly μ times
the size of the x impulse:
Vector3 impulseContact; Determine the impulse needed to remove all
velocity components at the contact (including y
and z planar velocities) – explored next.
float planarImpulse =
Math.Sqrt(impulseContact.y*impulseContact.y +
impulseContact.z*impulseContact.z);
Determine if the impulse to be applied falls within the range of static friction
if (planarImpulse > impulseContact.x * friction)
{ Apply dynamic friction if needed
impulseContact.y /= planarImpulse;
impulseContact.y *= friction * impulseContact.x;
impulseContact.z /= planarImpulse;
impulseContact.z *= friction * impulseContact.x;
}
Modifying Velocity Resolution
In order to introduce friction the following changes need
to be made to the previous velocity resolution algorithm:
Step 2: Determine the change in velocity (both linear and angular) at the
contact point for each object per unit of applied impulse.
Step 2 must now determine the change in velocity per unit impulse given
any combination of impulses in the three contact directions. In order to do
this, a matrix converting an input contact impulse vector into a
corresponding velocity change vector must be built.
Step 3: Invert the velocities determined in step 2
The inverse of the matrix produced in step two must be
generated (i.e. thereby transforming a desired change
in velocity into a corresponding impulse)
Modifying the Velocity Resolution Algorithm
Step 5. From the change in velocity we can calculate the impulse that
must be generated.
The inverted matrix must be used to determine the contact impulse
vector.
Additionally, the static/dynamic friction test (last slide) must be used to
determine frictional planar velocity change.
Determine (angular) velocity per unit of impulse
Previously the following code was employed:
Vector3 torquePerUnitImpulse =
Cross( relativeContactPosition, contactNormal )
Vector3 rotationPerUnitImpulse =
inverseInertiaTensor.Transform(torquePerUnitImpulse);
Vector3 velocityPerUnitImpulse =
Cross( rotationPerUnitImpulse, relativeContactPosition _);
Vector3 velocityPerUnitImpulseContact =
contactToWorld.TransformTranspose(velocityPerUnitImpulse);
The above approach must be extended to use all three components of
the basis matrix (and not just the contact normal).
In order to take the (equivalent) cross product of the relative contact
position and the contact basis matrix (which can be thought about in
terms of turning an impulse into a torque), a skew-symmetric matrix
is used.
Determine (angular) velocity per unit of impulse
Aside: Vector cross product is equivalent to multiplication by a
corresponding skew-symmetric matrix, i.e.: Given a vector
the vector product is equivalent to the following matrix-by-vector
multiplication:
Additionally, as
we have
Determine (angular) velocity per unit of impulse
Hence:
Matrix3 impulseToTorque Build a skew-symmetric matrix for the ‘cross’ product
= BuildSkewSymmetric(relativeContactPosition);
Determine the resultant torque per unit of applied impulse using the skew-symmetric matrix
Matrix3 torquePerUnitImpulse = impulseToTorque * contactToWorld;
Determine the resultant rotation per unit of applied impulse using matrix multiplication
Matrix3 rotationPerUnitImpulse =
inverseInertiaTensor * torquePerUnitImpulse;
The inverse cross product
is simply equivalent to a Matrix3 velocityPerUnitImpulse =
1 multiplication of the
rotationPerUnitImpulse * impulseToTorque;
skew-symmetric matrix
velocityPerUnitImpulse *= -1;
As before, the result is expressed in terms of contact coordinates
Matrix3 velocityPerUnitImpulseContact =
contactToWorld.Transpose() * velocityPerUnitImpulse;
Determine (angular) velocity per unit of impulse
The final matrix will transform an impulse in contact
coordinates into a velocity in contact coordinates.
If the contact is between two moveable rigid bodies,
then the same process can be performed for each
body and the results simply combined by using
matrix addition to add both matrices together.
Aside: See the recommend course text for an efficient means of
accomplishing this.
Determine (linear) velocity per unit of impulse
As before, the change in velocity per unit impulse due to linear motion
is found using:
In order to transform this vector-to-vector transform into a matrix
form that can be added to the angular matrix, the inverse mass is
expressed in a matrix form, i.e.: multiplying a vector by a scalar
quantity k is equivalent to transforming it by the matrix
Hence, in order to combine linear and angular
motion, the angular matrix need only be modified by
adding the inverse mass to diagonal elements (e.g.
matrix.M11 += inverseMass, etc.)
A finished game physics engine
With the above changes integrated, we
have built an iterative, impulse-based, rigidbody game physics engine.
The next section explores performance
enhancements within the engine.
Directed physics reading
Directed reading
• Read Chapter 15 of Game Physics
Engine Development (pp351-374)
on collision resolution with
frictional forces.
Summary
Today we
explored:
 How to
resolve
contacts
taking into
account
frictional
forces
Download