首页 > 其他分享 >14-Collision_resolution

14-Collision_resolution

时间:2024-03-13 15:14:22浏览次数:30  
标签:14 objects object Collision contact impulse velocity resolution linear

We I have a set of contact data from the collision detector, and have the rigid-body equations of motion, including torques and forces. We are now ready to combine the two and have rotating objects respond to contacts.

Impulses and Impulsive Torques

Different objects have a different resistance to being deformed and a different tendency to return to their original shape. If there is a tendency to return to their original shape, then the force begins to accelerate them apart until they are no longer deformed. To simulate this we instantly change the velocity of each object in the collision. The change in velocity is called an “ impulse”.

Now that we are dealing with rotating rigid bodies. If you bounce an object that is spinning on the ground, you will notice that the object not only starts to move back upward, but its angular velocity will normally change too. The collision affects bothlinear and angular velocities. Any force acting on an object generates both linear and angular acceleration.

An instantaneous change in velocity.In the same way that we have

\[f = m\ddot{p} \qquad \qquad [1.1] \]

for forces,we have

\[g = m\dot{p} \qquad \qquad [1.2] \]

一般时使用p而不是使用g,但是为了防止和位置(p)冲突所以使用了g。这个impulse和force是等价的。一些作用力不只是通过加速度来体现出来,有些是通过速度而不是加速度体现的。其实 \(\dot{p}应该是速度的改变吧,此处有疑问\)

Impulsive Torque

.

The linear component is given by

\[\ddot{p} = \frac{1}{m}f \qquad \qquad [1.3] \]

and the angular component by the torque

\[\tau = P_{f} \times f \qquad \qquad [1.4] \]

where the torque generates angular acceleration by

\[\ddot{\theta} = I^{-1}\tau \qquad \qquad [1.5] \]

In the case of the collision it stands to reason that the collision will generate a linear change in velocity (the impulse) and an angular change in velocity. An instantaneous angular change in velocity is called an “impulsive torque”.

\[u = I\dot{\theta} \qquad \qquad [1.6] \]

where the \(u\) is the impulsive torque. \(I\) is the inertia tensor, and $ \dot{\theta}$ is the angular velocity.该公式对应了上面的[1.2] (个人感觉此处应该是angular velocity的改变值)
This is the direct equivalent of equation 7.5, which dealt with linear impulses.And correspondingly the change in angular velocity $\Delta \dot{\theta} $ is

\[\Delta \dot{\theta} = I^{-1}u \qquad \qquad \qquad [14.1] \]

Impulses behave just like forces (就是Impulses和forces是一样的,都会产生linear 和angular分量,而Torque仅仅是关于angular的问题,不要混淆哦). In particular for a given impulse there will be both a linear component and an angular component.The impulsive torque generated by an impulse (impluse也会产生impulsive torque) is given by

\[u = P_{f}\times g \qquad \qquad [14.2] \]

for collisions the point of application \(P_{f}\)is given by the contact point and the origin of the object:

\[P_{f} = q - p \qquad \qquad [1.8] \]

where \(q\)is the position of the contact in world coordinates and \(p\) is the position of the origin of the object in world coordinates.

Rotating Collisions

The effect of the impulse at the collision is to have the points of each object in collision bounce apart. The movement of the colliding objects at the collision point still follows the same equations that we met in chapter 7. In other words, if we tracked the two collision points (one from each object) around the time of the collision, we’d see that their separating velocity is given by

\[v_{s}' = -cv_{s} \]

where \(v_{s}\) is the relative velocity of the objects immediately before the collision, is the relative velocity after the collision, and c is the coefficient of restitution. The constant c depends on the materials of both objects involved.

Depending on the characteristics of the objects involved, and the direction of the contact normal, this separation velocity will be made up of a different degree of linear and rotational motion. Figure shows different objects engaged in the same collision.In each part of the figure the closing velocity and the coefficient of restitution at the point of contact are the same, so the separating velocity is the same too.

  • The first object is lightweight and is colliding almost head on. For any force that is generated during the collision the corresponding torque will be small, because f is almost parallel to pf . Its bounce will be mostly linear, with only a small rotational component.
  • The second object is heavier but has a very small moment of inertia about the Z axis. It is colliding off center. Here the torque generated will be large, and because the moment of inertia is very small, there will be a big rotational response. The rotational response is so large, in fact, that the linear component isn’t large enough to bounce the object upward. Although the point of contact bounces back up (at the same velocity as the point of contact in each other case), it is the rotation of the object that is doing most of the separating, so the linear motion continues downward at a slightly slower rate. You can observe this if you drop a ruler on the ground in the configuration shown in figure 14.2. The ruler will start spinning away from the point of contact rapidly, but as a whole it will not leap back into the air. The rotation is taking the bulk of the responsibility for separating the points of contact.
  • The third object in the figure collides in the same way as the second. In this case, however, although the mass is the same, its moment of inertia is much greater. It represents an object with more mass in its extreme parts. Here the compression force causes a much lower amount of rotation. The linear impulse is greater and the impulsive torque is smaller. The object bounces linearly and the compression force reverses the direction of rotation, but the resulting angular velocity is very small.

Handling Rotating Collisions

Just as for particle collisions, we need two parts to our collision response.

  • First we need to resolve the relative motion of the two objects by applying impulse and impulsive torque. When we process a collision for velocity, we need to calculate four values: the impulse and impulsive torque for both objects in the collision.

  • Because we only check for collisions at the end of each frame, objects may have already passed into one another.So, second, we need to resolve any interpenetration that has occurred.

Collision Impulses

To resolve the relative motion of the two objects we need to calculate four impulses: linear and angular impulses for each object.
To calculate the impulse and impulsive force on each object we go through a series of steps:

  • We work in a set of coordinates that are relative to the contact.
  • We work out the change in velocity of the contact point on each object per unit impulse.
  • We will know the velocity change we want to see (in the next step), so we invert the result of the last stage to find the impulse needed to generate any given velocity change.
  • We work out what the separating velocity at the contact point should be, what the closing velocity currently is, and the difference between the two. This is the desired change in velocity.
  • From the desired change in velocity we can calculate the impulse that must be generated.
  • We split the impulse into its linear and angular components and apply them to each object

Change To Contact Corrdinates

Recall that each contact has an associated contact point and contact normal. If we use this point as the origin, and the contact normal as one axis, we can form an orthonormal basis around it: a set of three axes. Just as we have a set of
world coordinates and a set of local coordinates for each object, we will have a set of contact coordinates for each contact.
Since we are ignoring friction for now, we create an arbitrary set of axes by starting with the Y axis pointing down the world Y axis, The X axis we know already: it is the contact normal generated by the collision detector.

Velocity Change By Impulse

The Linear Component

The Linear Component
The linear component is very simple. The linear change in velocity for a unit impulse will be in the direction of the impulse, with a magnitude given by the inverse mass:

\[\Delta \dot{p}_{d} = m^{-1} \]

For collisions involving two objects, the linear component is simply the sum of the two inverse masses:

\[\Delta \dot{p}_{d} = m_{a}^{-1} + m_{b}^{-1} \]

The Angular Component

We’ll need to bring together three equations we have met at various points in the book. For convenience we’ll use \(q_{real}\) for the position of the contact relative to the origin of an object: $ q_{real} = q − p $

  • equation 14.2 tells us the amount of impulsive torque generated from a unit of impulse:

\[u = q_{real} \times \widehat{d} \]

where \(d\) is the direction of the impulse (in our case the contact normal).

  • equation 14.1 tells us the change in angular velocity for a unit of impulsive torque:

    \[\Delta \dot{ \theta } = I^{-1}u \]

  • And finally, equation 9.5 tells us the total velocity of a point.
Vector3 torquePerUnitImpulse = relativeContactPosition % contactNormal;
Vector3 rotationPerUnitImpulse = inverseInertiaTensor.transform(torquePerUnitImpulse);
Vector3 velocityPerUnitImpulse = rotationPerUnitImpulse % relativeContactPosition;

Impulse Change By Velocity

For frictionless collisions this step is incredibly simple. If we have a single value for the velocity change per unit impulse (call it \(d\)), then the impulse needed to achieve a given velocity change is

\[g = \frac{v}{d} \qquad \qquad [14.3] \]

where \(v\) is the desired change in velocity and \(g\) is the impulse required.

Calculating The Desired Velocity Change

This stage of the algorithm has two parts. First we need to calculate the current closing velocity at the contact point. Second we need to calculate the exact change in velocity we are looking for.

Calculating the Closing Velocity

As we saw earlier, velocity has both a linear and an angular component. We calculate its linear velocity and the linear velocity of the contact point due to rotation alone.

We can retrieve the linear velocity from an object directly; it is stored in the rigid body. To retrieve the velocity due to rotation we need to use equation 9.5 again. The total velocity of the contact point for one object is given by

Vector3 velocity = body->getRotation() % relativeContactPosition;
velocity += body->getVelocity();

This gives us a total closing velocity in world coordinates. We need the value in contact coordinates because we need to understand how much of this velocity is in
the direction of the contact normal and how much is at a tangent to this. The components of the velocity that are not in the direction of the contact normal represent how fast the objects are sliding past one another: they will become important when
we consider friction.The conversion uses the basis matrix in the now familiar way:

contactVelocity = contactToWorld.transformTranspose(velocity);
Calculating the Desired Velocity Change

As I mentioned at the start of the chapter, the velocity change we are looking for is given by the same equation we used for particles:

\[v'_{s} = -cv_{s}\Rightarrow \Delta v_{s} = -v_{s} - cv_{s} = -(1 + c)v_{s} \]

The value of the coefficient depends on the materials involved in the collision.

Calculating The Impulse

With the desired velocity change in hand, the impulse is given by equation 14.3.
Because we are not concerned with friction, we are only concerned with the impulse in the direction of the contact normal. In contact coordinates the contact normal is the X axis, so the final impulse vector is:

\[g_{contact} = \left[ \begin{array}{c} g \\ 0 \\ 0 \end{array} \right] \]

where \(g\) is the impulse,as earlier.

Applying The Impulse

To apply the impulse, we use equations 7.5 and 14.1. The first tells us that linear impulses change the linear velocity of the object according to the formula

\[\dot{p} = \frac{f}{m} \]

So the velocity change for the first object in the collision will be

Vector3 velocityChange = impulse * body[0]->getInverseMass()

The rotation change is given by equation 14.1:\(\Delta \dot{\theta} = I^{-1}u\) ,We first need to calculate the impulsive torque, \(u\), using equation 14.2 again:

\[u = q_{rel} \times g \]

Vector3 impulsiveTorque = impulse % relativeContactPosition;
Vector3 rotationChange = inverseInertiaTensor.transform(impulsiveTorque)

Resolving Interpentration

We have covered the procedure for representing the change in velocity when a collision happens. If the objects in our simulation were truly solid, this would be all that is needed.

Unfortunately the objects can pass into one another before we detect that a collision has occurred. The simulation proceeds in time steps, during which no checking takes place. By the end of a time step when collision detection occurs, two objects can have touched and passed into one another. We need to resolve this interpenetration in some way; otherwise objects in the game will not appear solid.

Choosing A Resolution Method

For rotating rigid bodies the situation is a little more complex. There are several strategies we could employ to resolve interpenetration.

Linear Projection

We could use the same algorithm as before: changing the position of each object so that it is moved apart in the direction of the contact normal. The amount of movement should be the smallest possible such that the objects no longer touch. For collisions involving two objects the amount each one moves is proportional
to its inverse mass.
Linear projection
Unfortunately it isn't very realistic. This is in contrast to the third part of the figure that shows how a real box would behave.

Velocity-Based Resolution

Velocity-based resolution
Another strategy used in some physics engines is to take into account the linear and angular velocities of the objects in the collision.At some point in their motion the two objects will have just touched. After that
time they will continue interpenetrating to the end of the time step. To resolve the interpenetration we could move them back to the point of first collision. We can approximate it by considering only the contact point on each object as generated by the collision detector. We can move these two points back alongthe paths they followed until they no longer overlap in the direction of the contact normal

Nonlinear Projection

Nonlinear projection
Rather than just moving the objects back linearly, we use a combination of linear and angular movement to resolve the penetration.
The theory is the same: we move both objects in the direction of the contact normal until they are no longer interpenetrating. The movement, rather than being exclusively(独占的,唯一的) linear, can also have an angular component.
Unlike linear projection, the balance between linear and angular velocity will depend on the inverse inertia tensor of each object. An object with a high moment of inertia tensor at the contact point will be less likely to rotate, so will take more of its motion as linear motion.

Relaxation

Relaxation resolves only a proportion of the interpenetration at one go. Relaxation is useful when there are lots of contacts on one object. As each contact is considered and resolved, it may move the object in such a way that other objects are now interpenetrated. For a brick in a wall, any movement in any direction will cause it to interpenetrate with another brick. This can cause problems with the order in which interpenetration resolution is carried out, and can leave the simulation with contacts that still have noticeable penetration.

By performing more interpenetration resolution steps, but having each one only resolve a proportion of the interpenetration, a set of contacts can have a more equitable say over where an object ends up. Each gets to resolve a little, and then the others take their turns. This typically is repeated several times. In situations where previously there would have been one or two contacts with obvious interpenetration, this method shares the interpenetration among all the conflicting contacts, which may be less noticeable.

Unfortunately relaxation also makes it more likely that interpenetration is noticeable at the end of an update when there are few collisions. It is beneficial to have all contacts share a small degree of interpenetration when the alternative is having one very bad contact, but in most cases it is undesirable and a full-strength resolution step is more visually pleasing.

Implementing Nonlinear Projection

We start knowing the penetration depth of the contact.Our goal is to find the proportion of this movement that will be contributed by linear and angular motion for each object.
We first make an assumption: we imagine the objects we are simulating were pushed together so that they deformed. this deformation causes a force that pushes the objects apart. This force, according to D’Alembert’sprinciple, has both linear and angular effects.

Calculating the Components

For velocity we were interested in the amount of velocity change caused by the rotation change from a single unit of impulse. This quantity is a measure of how resistant the object is to being rotated when an impulse or force is applied at the contact point.
To resolve penetration we use exactly the same sequence of equations. We find the resistance of the object to being moved in both a linear and angular way.

Recall that the resistance of an object to being moved is called its "inertia". So we are interested in finding the inertia of each object in the direction of the contact normal. This inertia will have a linear component and a rotational component.
The linear component of inertia is, as before, simply the inverse mass. The angular component is calculated using the same sequence of operations that we used previously.

// We need to work out the inertia of each object in the direction
// of the contact normal, due to angular inertia only.
for (unsigned i = 0; i < 2; i++)
{
    if (body[i])
    {
        Matrix3 inverseInertiaTensor;
        body[i]->getInverseInertiaTensorWorld(&inverseInertiaTensor);
        // Use the same procedure as for calculating frictionless
        // velocity change to work out the angular inertia.
        Vector3 angularInertiaWorld = relativeContactPosition[i] % contactNormal;
        angularInertiaWorld = inverseInertiaTensor.transform(angularInertiaWorld);
        angularInertiaWorld = angularInertiaWorld % relativeContactPosition[i];
        angularInertia[i] = angularInertiaWorld * contactNormal;
        // The linear component is simply the inverse mass.
        linearInertia[i] = body[i]->getInverseMass();
        // Keep track of the total inertia from all components.
        totalInertia += linearInertia[i] + angularInertia[i];
    }
}

At the end of this loop we have the four values (two for single-body collisions) that tell us the proportion of the penetration to be resolved by each component ofeach rigid body. The actual amount each object needs to move is found by

real inverseInertia = 1 / totalInertia;
linearMove[0] = penetration * linearInertia[0] * inverseInertia;
linearMove[1] = -penetration * linearInertia[1] * inverseInertia;
angularMove[0] = penetration * angularInertia[0] * inverseInertia;
angularMove[1] = -penetration * angularInertia[1] * inverseInertia;
Applying the Movement

Applying the linear motion is simple. The linear move value gives the amount of motion required, and the contact normal tells us the direction in which the movement should take place:

body[i]->position += contactNormal * linearMove[i];

The angular motion is a little more difficult. We know the amount of linear movement we are looking for; we need to calculate the change in the orientation quaternion that will give it to us.
We do this in three stages.

  • First we calculate the rotation needed to move the contact point by one unit.[rotation ---> move one unit]
  • Second, we multiply this by the number of units needed (i.e.,the angularMove value). [ angularMove * rotation -> needed rotation ]
  • Finally we apply the rotation to the orientation quaternion. [needed rotation -> orientation quaternion]

We can calculate the direction in which the object needs to rotate, using the same assumption that the rotation is caused by some kind of impulse. If an impulse were exerted at the contact point, the change in rotation would be

\[\Delta \dot{\theta} = I^{-1}u = I^{-1} (q_{rel} \times g) \]

where \(q_{rel}\) is the relative position of the contact point, \(u\) is the impulsive torque generated by the impulse, and g is the impulse in the direction of the contact normal, as before. In code, this is

Vector3 inverseInertiaTensor;
body->getInverseInertiaTensorWorld(&inverseInertiaTensor);
Vector3 impulsiveTorque = relativeContactPosition % contactNormal;
Vector3 impulsePerMove =inverseInertiaTensor.transform(impulsiveTorque);

This tells us the impulsive torque needed to get one unit of motion. To find the rotation needed to get one unit of movement we simply multiply through by the inertia:

Vector3 rotationPerMove = impulsePerMove * 1/angularInertia;

The rotationPerMove vector now tells us the rotation we need to get one unit of movment. And we know the total movement we want is angularMove, so we know the total rotation to apply is

Vector3 rotation = rotationPerMove * angularMove

Avoiding Excessive Rotation

There are two issues to address with the algorithm presented so far.The first is an assumption that slipped in without being commented on, and the second is a potential problem that can cause instability and odd-looking behavior. Both are related to objects being rotated too much as they are moved out of penetration.

Figure shows an object that has been severely interpenetrated. If the moment of inertia of the object is small but its mass is large, then most of the extraction will be down to angular movement. Clearly, no matter how much angular movement is imposed, the contact point will never get out of the object. The example is extreme, of course, but the problem is very real.

The instant an object begins rotating from an impulsive torque, the contact point will also begin to move. For both issues we need to limit the amount of rotation that can be part of our penetration resolution. Keeping this value small means that our small-rotation assumption is valid, and that we minimize the chance of causing other interpenetrations while resolving one.

We can simply check that the values of angularMove are not too great. If they are, we can transfer some of the burden from them onto the corresponding linearMove component.
Some developers use a fixed amount: not allowing the angular move value to be greater than 0.5, for example. This works well as long as the objects in the simulation are all roughly the same size. If some objects are very large, then a suitable limit for
them may be unsuitable for smaller objects, and vice versa.

It is also possible to express the limit in terms of a fraction of a revolution that the object can make. We could limit the rotation so that the object never turns through more than 45◦, for example. This accounts for differences in size, but it is more complex to work out the equivalent angular move for a specific angle of
rotation. A simple alternative is to scale the angular move by the size of the object (where the size of the object can be approximated by the magnitude of the relative contact position vector). Therefore larger objects can have more angular movement.

☀️

The Collision Resolution Process

I mentioned in the introduction to the book that the

标签:14,objects,object,Collision,contact,impulse,velocity,resolution,linear
From: https://www.cnblogs.com/ultramanX/p/18070671

相关文章

  • 14---DVI电路设计
    视频链接DVI硬件电路设计01_哔哩哔哩_bilibiliDVI电路设计1、DVI的简介DVI(DigitalVisualInterface),即数字视频接口。它是1998年9月,在Intel开发者论坛上成立的,由SiliconImage、Intel(英特尔)、Compaq(康柏)、IBM(国际商业机器公司)、HP(惠普)、NEC(日本电气股份有限公司......
  • Linux软件高级编程-网络--TCP通信--day14
    TCP包头:1.序号:发送端发送数据包的编号2.确认号:已经确认接收到的数据的编号(只有当ACK为1时,确认号才有用)TCP为什么安全可靠:1.在通信前建立三次握手连接  SYN    SYN+ACK    ACK 2.在通信过程中通过序列号和确认号保障数据传输的完整性  本次......
  • 错误:在 /tmp/easy_install-rad8_t5b/PyQt5-5.14.0.tar.gz #15 中找不到安装脚本
    thePyQt55.14.0isbrokenbecausecan'tnotinstallonresppi3.youcantoinstallaversionofPyQt5thatworkingfineonresp.followthesteps:PyQt55.14.0已损坏,因为无法无法安装在resppi3上。您可以安装一个在resp上运行良好的PyQt5版本,请按照以下......
  • 力扣148排序链表--复习归并和快速排序
    递归的归并排序归并排序主要流程是拆分--排序--合并--排序--合并//拆分voidmergeSort(vector<int>&nums,intstart,intend){ if(start>=end)return; intmid=start+(end-start)/2; mergeSort(nums,start,mid); mergeSort(nums,mid+1,end); //最后一层排......
  • 找不到mfc140u.dll怎么办?修复缺失mfc140u.dll的多种方案分享
    mfc140u.dll文件是一个重要的动态链接库文件,它在Windows操作系统中发挥着关键的作用。由于各种原因,例如应用程序冲突或系统错误等,mfc140u.dll文件有时会出现丢失的情况。一旦发生这种问题,运行依赖此文件的应用程序将无法正常启动,可能导致错误提示或应用程序崩溃。因此,解决mfc14......
  • VMware安装MacOS14(Sonoma)
    如果你想在Windows电脑上体验苹果最新的macOS14Sonoma系统!那么跟着我步骤来进行安装吧~安装步骤:1、首先下载并安装VMWare虚拟机软件【官网下载】下载【VMWareUnlocker】,以管理员身份运行win-install3.下载macOS14索诺玛(Sonoma)的ISO系统文件【点击下载】......
  • 第143篇:手写vue-router,实现router-view
    好家伙, 今天来手写我们的老伙计vue-router, 1.替换router新开一个项目,并使用我们手写的router 2.大致结构letVue;//保存vue的构造函数classVueRouter{constructor(options){}}VueRouter.install=(_Vue)=>{Vue=_Vue;//备......
  • *【莫比乌斯反演】数表[SDOI2014]
    问题有一张\(N\timesN\)的数表(\(N=10^5\)),其第\(i\)行第\(j\)列(\(1\lei\len\),\(1\lej\lem\))的数值为能同时整除\(i\)和\(j\)的所有自然数之和。有T次询问,每次询问给定\(n,m,A\),计算数表(1,1)至(n,m)中不大于\(A\)的数之和(\(|A|\le10^9\))。每组数据输出一行一个整数......
  • P8612 [蓝桥杯 2014 省 AB] 地宫取宝
    https://www.luogu.com.cn/problem/P8612#submit原始暴搜代码,没有记忆化,会tle#include<iostream>#include<vector>#include<algorithm>#include<math.h>#include<sstream>#include<string>#include<string.h>#include<iomanip&g......
  • 14_访问者模式
    访问者模式是一种行为型设计模式,它允许在不改变被访问对象结构的前提下,定义对这些对象的新操作。访问者模式将操作和对象结构分离,使得可以在不修改对象结构的情况下添加新的操作。访问者模式有四个主要角色:抽象访问者(Visitor):定义了访问者可以访问的对象的接口,包含了一系列的访......